1. 程式人生 > 其它 >前端工作筆記(一)

前端工作筆記(一)

雙指標解決NSum問題

1.兩數之和

public int[] twoSum(int[] nums, int target) {
        /**
         *  首先,對於該題要求返回原始陣列下標,這裡就要求不能手動排序
         *  所以二分的思路行不通,
         *  但是這裡可以使用雜湊表,降低時間複雜度。使用雜湊表時,由於雜湊表剛開始並沒有建立啊
         *
         */
        Map<Integer, Integer> map = new HashMap<>();
        for (int i = 0; i < nums.length; i++) {
            int need = target - nums[i];
            if (map.containsKey(need)){
                return new int[]{i, map.get(need)};
            }
            map.put(nums[i], i);
        }
        return null;
    }

此時表不能進行排序。因為人家要求返回原始陣列下標。
這裡剛開始遍歷時,雜湊表裡並沒有資料,但是如果前面某個數事最後要返回的那個數字,在後面遍歷的時候一定會和前面的資料配對,也就是說雜湊表裡這時候有資料了。

2.三數之和

[-1,0,1,2,-1,-4]
排序之後是:
[-4, -1, -1, 0, 1, 2]
分析:依次選取第一個第二個數,

  1. 對於第一個數來說,不能選取重複的,因為選取了第一個數為-1,第二次再以-1作為第一個數的話,第二個數得到的結果一定是第一個-1得到的結果的子集。
  2. 對於第2個數來說,第二個數也不能相同,這樣得到的一定是相同的結果集。

class Solution {
public List<List> threeSum(int[] nums) {
//首先是排序為有序陣列
Arrays.sort(nums);
int n = nums.length;
//存放最終結果
List<List> ans = new ArrayList<>();

    for (int i = 0; i < n; i++) {
        //對於選取的第一個數字
        if (i > 0 && nums[i] == nums[i - 1]) {
            continue;
        }
        //每一輪開始的條件:
        int j = i + 1;
        int k = n - 1;
        while (j < k) {
            //能夠提前判斷並且結束
            while (j > i + 1 && j < n && nums[j] == nums[j - 1]){
                j++;
            }
            if (j >= k) {
                break;
            }

            int sum = nums[i] + nums[j] + nums[k];
            if (sum == 0){
                //注意新增結果集的操作,新增之後,還是要判斷更新j的值
                ans.add(Arrays.asList(nums[i], nums[j], nums[k]));
                j++;
            }else if (sum > 0){
                k--;
            }else if (sum < 0){
                j++;
            }
        }
    }
    return ans;
}

}

  1. 最接近的三數之和
public int threeSumClosest(int[] nums, int target) {
        /**
         * 為了找到最接近target的三數之和,必須要使用取絕對值函式,但是這裡要謹記,
         * 對於初始值應該讓其初始化為陣列中的元素之和,不能隨意的初始化。
         */
        Arrays.sort(nums);
        int n = nums.length;
        int res = nums[0] + nums[1] + nums[2];

        for (int i = 0; i < n; i++) {
            if (i > 0 && nums[i] == nums[i - 1]){
                continue;
            }
            int j = i + 1;
            int k = n - 1;
            while (j < k){
                if (j > i + 1 && j < n && nums[j] == nums[j - 1]){
                    j++;
                }
                if (j >= k){
                    break;
                }
                int sum = nums[i] + nums[j] + nums[k];
//              res = Math.min(Math.abs(target - sum), res);
                res = Math.abs(sum - target) < Math.abs(res -target) ? sum : res;
//                if(Math.abs(sum - target) < Math.abs(res - target)){
//                    res = sum;
//                }
                if (sum == target){
                    return sum;
                }else if (sum > target){
                    k--;
                }else if (sum < target){
                    j++;
                }
            }
        }
        return res;
    }

18.四數之和

public List<List<Integer>> fourSum(int[] nums, int target) {
        Arrays.sort(nums);
        List<List<Integer>> res = new ArrayList<>();
        int n = nums.length;

        for (int i = 0; i < n; i++) {
            //控制第一個數
            if (i > 0 && nums[i] == nums[i - 1]){
                continue;
            }
            //控制第二個數
            for (int j = i + 1; j < n; j++) {
                if (j > i + 1 && nums[j] == nums[j - 1]){
                    continue;
                }

                int k = j + 1;
                int p = n - 1;
                while (k < p){
                    while (k > j + 1 && k < n && nums[k] == nums[k - 1]){
                        k++;
                    }
                    while (k >= n){
                        break;
                    }
                    //這裡是因為leecode給出的測試案例太大,溢位,最好轉為long型別
                    long sum = (long) nums[i] + nums[j] + nums[k] + nums[p];
                    if (sum == target){
                        res.add(Arrays.asList(nums[i], nums[j], nums[k], nums[p]));
                        k++;
                    }
                    else if (sum > target){
                        p--;
                    } else if (sum < target) {
                        k++;
                    }
                }
            }
        }
        return res;
    }

這樣對於NSum問題來說就有一個很好的解決方法:
直接使用3Sum作為迭代終點,其他的依次呼叫(n-1)Sum即可