zoukankan      html  css  js  c++  java
  • LintCode 数组(一)

    恢复旋转排序数组 

    最大子数组

    两数之和

    三数之和 

    加一

    删除元素

    买卖股票的最佳时机

    删除排序数组中的重复数字

    合并排序数组

    两数组的交

    移动零

    移动零

    将一个数组中的 0 移动到数组的最后面,非零元素保持原数组的顺序。必须在原数组上操作。

    public void moveZeroes(int[] nums) {
        if(nums==null || nums.length==0){
            return;
        }
        int insertPos = 0;
        for(int i=0; i<nums.length; i++){
            if(nums[i]!=0){
                nums[insertPos++] = nums[i];
            }
        }
        while(insertPos<nums.length){
            nums[insertPos++] = 0;
        }
    }

    两数组的交

    样例:nums1 = [1, 2, 2, 1], nums2 = [2, 2], 返回 [2].

    解答一:用两个HashSet

    public int[] intersection(int[] nums1, int[] nums2) {
        Set<Integer> set = new HashSet<Integer>();
        Set<Integer> inter = new HashSet<>();
        for(int i=0; i<nums1.length; i++){
            set.add(nums1[i]);
        }
        for(int j=0; j<nums2.length; j++){
            if(set.contains(nums2[j])){
                inter.add(nums2[j]);
            }
        }
        int[] rst = new int[inter.size()];
        int k = 0;
        for(Integer s: inter){
            rst[k++] = s;
        }
        return rst;
    }

    解答二:对两个数组排序,然后各用一个指针遍历。

    public int[] intersection(int[] nums1, int[] nums2) {
        Set<Integer> set = new HashSet<Integer>();
        Arrays.sort(nums1);
        Arrays.sort(nums2);
        int i=0, j=0;
        while(i<nums1.length && j<nums2.length){
            if(nums1[i]<nums2[j]){
                i++;
            }else if(nums1[i]>nums2[j]){
                j++;
            }else{
                set.add(nums1[i]);
                i++;
                j++;
            }
        }
        int[] arr = new int[set.size()];
        int k = 0;
        for(Integer s: set){
            arr[k++] = s;
        }
        return arr;
    }

    解答三:利用HashMap

    public int[] intersection(int[] nums1, int[] nums2){
        Map<Integer, Integer> map = new HashMap<>();
        for(int i = 0; i < nums1.length; ++i){
            if(!map.containsKey(nums1[i])){
                map.put(nums1[i], 1);
            }
        }
        List<Integer> list = new ArrayList<>();
        for(int i = 0; i < nums2.length; ++i){
            if(map.containsKey(nums2[i])){
                list.add(nums2[i]);
                map.remove(nums2[i]);
            }
        }
        int[] res = new int[list.size()];
        int k = 0;
        for(Integer num : list){
            res[k++] = num;
        }
        return res;
    }

    解答四:对num2排序,然后遍历num1中的数,在num2中进行二分查找,找到就放入set中。

     

    两数之和

    给一个整数数组,找到两个数使得他们的和等于一个给定的数 target

    public int[] twoSum(int[] numbers, int target) {
        HashMap<Integer, Integer> hash = new HashMap<>();
        int[] result = new int[2];
        for(int i=0; i<numbers.length; i++){
            if(hash.get(numbers[i]) == null){
                hash.put(target-numbers[i], i);
            }else{
                result[0] = hash.get(numbers[i]) +1;
                result[1] = i + 1;
            }
        }
        return result;
    }

    恢复旋转排序数组

    给定一个旋转排序数组,在原地恢复其排序。

    public void recoverRotatedSortedArray(ArrayList<Integer> nums) {
        for(int i=0; i<nums.size()-1; i++){
            if(nums.get(i)>nums.get(i+1)){
                recover(nums, 0, i);
                recover(nums, i+1, nums.size()-1);
                recover(nums, 0, nums.size()-1);
            }
        }
    }
    private void recover(ArrayList<Integer> nums, int left, int right){
        while(left<right){            
            int tmp = nums.get(left);
            nums.set(left, nums.get(right));
            nums.set(right, tmp);
            left++;
            right--;
            
        }
    }

    最大子数组和

    给定一个整数数组,找到一个具有最大和的子数组,返回其最大和。

    解答一:暴力

    public int maxSubArray(int[] nums) {
        if (nums == null || nums.length == 0) {
            return 0;
        }
        int maxSum = Integer.MIN_VALUE;
        for(int i=0; i<nums.length; i++){
            int sum = 0;
            for(int j=i; j<nums.length; j++){
                sum += nums[j];
                maxSum = Math.max(maxSum, sum);
            }
        }
        return maxSum;
    }

     解答二:动态规划。遍历,一个变量保存到当前位置时的最大值,另一个变量保存全局最大值。

    public int maxSubArray(int[] nums) {
        int maxEndingHere = nums[0]; // 当前位置的最大值
        int max = nums[0];  // 全局最大值
        for(int i=1; i<nums.length; i++){
            maxEndingHere = Math.max(nums[i], maxEndingHere+nums[i]);
            max = Math.max(max, maxEndingHere);
        }
        return max;
    }

    解答三:贪婪算法。遍历,对所有数从左到右累加,同时判断选择最大和,如果当前sum为负,则再加下一个数时,把sum替换为0。

    public int maxSubArray(int[] nums){
        int max = Integer.MIN_VALUE;
        int sum = 0;
        for(int i=0; i<nums.length; i++){
            sum += nums[i];
            max = Math.max(max, sum);
            sum = Math.max(0, sum); //如果sum出现负,就不用在此sum为负的基础上再加下一个数。把sum改成0
        }
        return max;
    }

    加一

    给定一个非负数,表示一个数字数组,在该数的基础上+1,返回一个新的数组。

    样例:给定 [1,2,3] 表示 123, 返回 [1,2,4].  给定 [9,9,9] 表示 999, 返回 [1,0,0,0].

    public int[] plusOne(int[] digits) {
        int carries = 1;
        for(int i=digits.length-1; i>=0 && carries>0; i--){
            int sum = digits[i] + carries;
            digits[i] = sum % 10;
            carries = sum/10;
        }
        
        if(carries==0){
            return digits;
        }
        int[] rst = new int[digits.length+1];
        rst[0] = 1;
        for(int j=0; j<digits.length; j++){
            rst[j+1] = digits[j];
        }
        return rst;
    }

    删除元素

     给定一个数组和一个值,在原地删除与值相同的数字,返回新数组的长度。

    解答:用左右两个指针,left的值为val时,把right赋给left,right--

    public int removeElement(int[] nums, int val) {
        int left = 0;
        int right = nums.length-1;
        while(left<=right){
            if(nums[left]==val){
                nums[left] = nums[right];
                right--;
            }else{
                left++;
            }
        }
        return right+1;
    }

    买卖股票的最佳时机

     假设有一个数组,它的第i个元素是一支给定的股票在第i天的价格。如果你最多只允许完成一次交易(例如,一次买卖股票),设计一个算法来找出最大利润。

    样例:给出一个数组样例 [3,2,3,1,2], 返回 1 

    解答:遍历数组,每次都更新最大利润和最小值。

    public int maxProfit(int[] prices) {
        if(prices==null || prices.length==0){
            return 0;
        }
        int min = prices[0];
        int maxpro = 0; 
        for(int i=1; i<prices.length; i++){
            maxpro = Math.max(maxpro, prices[i]-min);
            min = Math.min(min, prices[i]);
        }
        return maxpro;
    }

    删除排序数组中的重复数字

    给定一个排序数组,在原数组中删除重复出现的数字,使得每个元素只出现一次,并且返回新的数组的长度。

    解答:两个指针。i从头到尾遍历数组,遇到不同的,把值赋给count

    public int removeDuplicates(int[] nums) {
        int count = 1;
        for(int i=1; i<nums.length; i++){
            if(nums[i]!=nums[count-1]){
                nums[count++] = nums[i];
            }
        }
        return count;
    }

    合并排序数组

    (一)两个数组A,B。A中个数为m,B中个数为n。假设A有足够的容量,把B合并到A中,成为一个有序数组。

    public void merge(int[] A, int m, int[] B, int n){
        int i = m-1;
        int j = n-1;
        int k = m+n-1;
    
        while(i>=0 && j>=0){
            if(A[i] > B[j]){
                A[k--] = A[i--];
            }else{
                A[k--] = B[j--];
            }
        }
        while(i>=0){
            A[k--] = A[i--];
        }
        while(j>=0){
            A[k--] = B[j--];
        }
    }

    (二)合并两个排序的整数数组A和B变成一个新的数组。

    public int[] mergeSortedArray(int[] A, int[] B) {
        int lena = A.length;
        int lenb = B.length;
        int[] rst = new int[lena+lenb];
        
        int i=0, j=0, k=0;
        while(i<lena && j<lenb){
            if(A[i]<=B[j]){
                rst[k++] = A[i++];
            }else{
                rst[k++] = B[j++];
            }
        }
        while(i<lena){
            rst[k++] = A[i++];
        }
        while(j<lenb){
            rst[k++] = B[j++];
        }
        return rst;
    }

    三数之和

    给出一个有n个整数的数组S,在S中找到三个整数a, b, c,找到所有使得a + b + c = 0的三元组。

    解答:先把数组排序。用三个指针,i从头到尾遍历,left=i+1,right=length-1。把这三个数相加,结果小于0则i++,大于0则j--。

    public ArrayList<ArrayList<Integer>> threeSum(int[] numbers) {
        ArrayList<ArrayList<Integer>> list = new ArrayList<>();
        if(numbers==null || numbers.length<3){
            return list;
        }
        
        Arrays.sort(numbers);
        
        for(int i=0; i<numbers.length-2; i++){
            int left = i+1;
            int right = numbers.length-1;
            while(left<right){
                int sum = numbers[i] + numbers[left] + numbers[right];
                if(sum==0){
                    ArrayList<Integer> tmp = new ArrayList<>();
                    tmp.add(numbers[i]);
                    tmp.add(numbers[left]);
                    tmp.add(numbers[right]);
                    if(list.contains(tmp) == false){
                        list.add(tmp);
                    }
                    left++;
                    right--;
                }else if(sum < 0){
                    left++;
                }else{
                    right--;
                }                
            }
        }
        
        return list;
    }
  • 相关阅读:
    UnknownHostException: xxx,使用nacos远程调用服务(负载均衡)报错
    Failed to bind properties under 'logging.level' to java.util.Map<java.lang.String, java.lang.String>日志级别的问题
    JS 如何返回到父页面?多重跳转之后返回到初始页(父页面)?或者说返回父页面的父页面?
    绝对路径${pageContext.request.contextPath}用法及其与web.xml中Servlet的url-pattern匹配过程
    VS在release模式下进行调试
    visual studio 运行找不到dll库
    C++ 字符串格式化
    SWIG使用遇到的问题
    其他技术---域名中转
    mongoDB增删改查(命令行操作数据库)
  • 原文地址:https://www.cnblogs.com/hesier/p/5634427.html
Copyright © 2011-2022 走看看