LintCode 數組(一)

恢復旋轉排序數組 

最大子數組

兩數之和git

三數之和 

加一

刪除元素

買賣股票的最佳時機算法

刪除排序數組中的重複數字

合併排序數組

兩數組的交數組

移動零spa

 

移動零設計

將一個數組中的 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;
    }
}

 

 

兩數組的交code

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

解答一:用兩個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;
}

解答二:對兩個數組排序,而後各用一個指針遍歷。three

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;
}
相關文章
相關標籤/搜索