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;
    }
  • 相关阅读:
    mysql复制那点事
    全排列问题
    56. Merge Interval
    2. Add Two Numbers
    20. Valid Parentheses
    121. Best Time to Buy and Sell Stock
    120. Triangle
    96. Unique Binary Search Trees
    91. Decode Ways
    72. Edit Distance
  • 原文地址:https://www.cnblogs.com/hesier/p/5634427.html
Copyright © 2011-2022 走看看