SnowyStoat

第一题 两数之和

给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。

你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。

你可以按任意顺序返回答案。

示例 1:

输入:nums = [2,7,11,15], target = 9 输出:[0,1] 解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。 示例 2:

输入:nums = [3,2,4], target = 6 输出:[1,2] 示例 3:

输入:nums = [3,3], target = 6 输出:[0,1]

提示:

2 <= nums.length <= 104; -109 <= nums[i] <= 109; -109 <= target <= 109; 只会存在一个有效答案 进阶:你可以想出一个时间复杂度小于 O(n2) 的算法吗?

解题:

首先想到的是 两层循环遍历,第一层取一个数,然后第二层,这个数后面的数逐个和这个数相加

看是否等于目标值!

例如:

for(int i = 0;i<nums.length-1;i++){
    for(int j = i+1;j<=nums.length-1;j++){
        if(nums[i]+nums(j) == target)
            return new int[]{i,j};
    }
}

时间复杂度为O(n^2);

更好的性能的解法是:利用map,空间换时间

具体定义一个map,key为nums的值,value为数组的index

例如 array[0] = 1 就是 map.put(1,0)

然后遍历数组,使用map.containsKey()查找

具体如下:

map.put(array[0],0);
for(int i=1;i<array.length;i++){
    if(map.containsKey(target-array[i])){
        return new int[]{map.get(target-nums[i]),i};
    } else {
        map.put(nums[i],i);
    }
    throw new IllegalArgumentException("No two sum solution");
}

这样的话,时间复杂度就降为O(n)

第三题 无重复字符的最长子串

给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。

示例 1:

输入: s = “abcabcbb” 输出: 3 解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。

示例 2:

输入: s = “bbbbb” 输出: 1 解释: 因为无重复字符的最长子串是 “b”,所以其长度为 1。

示例 3:

输入: s = “pwwkew” 输出: 3 解释: 因为无重复字符的最长子串是 “wke”,所以其长度为 3。 请注意,你的答案必须是 子串 的长度,“pwke” 是一个子序列,不是子串。

示例 4:

输入: s = "" 输出: 0

提示:

0 <= s.length <= 5 * 104; s 由英文字母、数字、符号和空格组成

线性结构!从左到右!不重复子串是连续的!

计算长度,需要相对位置,开始位置,结束位置。

如果是用C语言,会想到用两个指针,start end。

end只会逐个递增,所以用遍历就行。

start会随着end的遍历而变化,遇到重复,就在之前那个字符出现位置+1

要记录元素之前已经存在的位置。(用数组或者map喽)

我们以 abcabcbb为例,一开始 start end都在a(0)位置。然后end向右递增,

直到(3)位置,a重复,start移到第一个a位置+1;0+1即b(1)位置。

这里我们要记录字符上一次出现的位置信息。题目规定 s 由英文字母、数字、符号和空格组成

ASCII码128个。用int数组来解决。

// 记录每个字符位置
int[] last = new int[128];
//初始化每个字符的位置
for(int i = 0; i < 128; i++) {
    last[i] = -1;
}

int res = 0;//字串长度
int start = 0; //开始位置
for(int i = 0; i < n; i++) {
    int ascii = s.charAt(i);//char字符转化为ascii码数字
    System.out.println("index==="+ index);
	//判断是否有元素重复,如果有就在重复元素的索引位置+1;
    start = Math.max(start, last[index] + 1);
    //重新计算距离,然后和之前的做比较,取最大的。
    res   = Math.max(res, i - start + 1);
    last[ascii] = i;//存当前字符的位置。
}

return res;

如果不使用数组,也可以使用map来存储(字符:位置)的映射关系

 public static int lenSubString(String s){

     int len = 0;//字串长度
     int start = 0;
     Map<Character,Integer> subMap = new HashMap<>(s.length());
     for(int i = 0;i<s.length();i++){
         //重置开始位置
         start = Math.max(start,subMap.getOrDefault(s.charAt(i),-1)+1);
         //计算和比较字串长度
         len = Math.max(len,i-start+1);
         //放入 字符:位置 映射 关系
         subMap.put(s.charAt(i),i);
     }
     return len;
}