【兩數之和】----LeetCode算法題(一)

1、題目基本信息

題目傳送門--兩數之和數組

級別:【簡單】
/**
 * 【兩數之和】 給定一個整數數組 nums和一個目標值 target,請你在該數組中找出和爲目標值的那兩個整數,並返回他們的數組下標。
 * 
 * 你能夠假設每種輸入只會對應一個答案。可是,你不能重複利用這個數組中一樣的元素。
 * 
 * 示例:
 * 
 * 給定 nums = [2, 7, 11, 15], target = 9
 * 
 * 由於 nums[0] + nums[1] = 2 + 7 = 9 因此返回 [0, 1]
 * 
 * @Author jiawei huang
 * @Since 2019年8月8日
 * @Version 1.0
 */
複製代碼

2、解題思路

  • 一、最簡單、最粗暴的方式就是來2層for循環,這種解法時間複雜度爲O(n^2) ,不推薦,效率低。bash

  • 二、因爲是兩數之和等於某一個數,那麼咱們很容易就得出一個數學公式A+B=C,咱們作一下變換,獲得A=C-B,因爲咱們已知的是C,顯然等式2比等式1更加容易求值,同時由於變量有兩個,小編想到的是咱們一個變量存起來,一個變量進行一次查找比較,所以就有了以下題解思路:ui

    一、遍歷一遍數組,而後將每一個值與target作差存起來,同時存該數的下標;spa

    二、直到找到就返回;code

    三、時間複雜度爲O(n),空間複雜度也是O(n)leetcode

3、代碼演示

【解法一】get

/**
 * 小編本身的解法:9ms
 * 
 * @param nums
 * @param target
 * @return
 */
public static int[] twoSum(int[] nums, int target) {
    int[] returnArr = null;
    
    // 若是數組是空的,或者數組的長度爲0,直接返回
    if (null == nums || nums.length == 0) {
    	return returnArr;
    }
    
    Map</* 差值 */Integer, /* 下標 */ Integer> dataMap = new HashMap<>();
    // 既然要知道目標是第幾位,不免要知道數組的下標
    for (int i = 0; i < nums.length; i++) {
    	Integer subNum = nums[i];
    	Integer key = target - subNum;
    	if (dataMap.containsKey(subNum)) {
    		// 注意,賦值操做也是耗時的
    		returnArr = new int[2];
    		returnArr[1] = i;
    		returnArr[0] = dataMap.get(subNum);
    	} else {
    		dataMap.put(key, i);
    	}
    }
    
    return returnArr;
}
複製代碼

【解法二】數學

/**
 * 針對解法一,小編去除了賦值操做,時間變成6ms
 * 
 * @param nums
 * @param target
 * @return
 */
public static int[] twoSumWithSetValue(int[] nums, int target) {
    // 若是數組是空的,或者數組的長度爲0,直接返回
    if (null == nums || nums.length == 0) {
    	return null;
    }
    
    Map</* 差值 */Integer, /* 下標 */ Integer> dataMap = new HashMap<>();
    // 既然要知道目標是第幾位,不免要知道數組的下標
    for (int i = 0; i < nums.length; i++) {
    	Integer subNum = nums[i];
    	Integer key = target - subNum;
    	if (dataMap.containsKey(subNum)) {
	    return new int[] { dataMap.get(subNum), i };
    	}
    	dataMap.put(key, i);
    }
    return null;
}
複製代碼

【解法三】string

// leetcode大神解法,這解法牛,1ms,但小編沒看懂,主要有下面幾個疑問,麻煩留言區討論。
public int[] twoSumOneMs(int[] nums, int target) {
    int indexArrayMax = 2047;
    int[] indexArrays = new int[indexArrayMax + 1];
    int diff = 0;
    for (int i = 0; i < nums.length; i++) {
    	diff = target - nums[i];
    	if (indexArrays[diff & indexArrayMax] != 0) {
    		return new int[] { indexArrays[diff & indexArrayMax] - 1, i };
    	}
    	indexArrays[nums[i] & indexArrayMax] = i + 1;
    }
    throw new IllegalArgumentException("No two sum value");
}
複製代碼

這解法牛,耗時僅1ms,但小編沒看懂,主要有下面2個疑問,麻煩留言區討論。it

  • 一、爲何數組大小要設置成2048?
  • 二、爲何與運算&的數據indexArrayMax要選擇成20470111 1111 1111而不是其餘值?
相關文章
相關標籤/搜索