持续更新ing!   

本博客题目来源于牛客网上的企业高频面试题,对应到leetcode中的题目序号。

 

1.两数之和

 

给定一个整数数组 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]

 

 

思路步骤:

1. 创建一个 map

2. 用 for 循环遍历 nums 数组

3. 用 target 减nums[i], 计算哪个数能跟当前的数字相加得到 target

4. 检查map里有没有这个数,如果有则返回结果,如果没有则把nums[i]当作key,i当做value放入map中(为什么是nums[i]当作key?因为map.has()方法检查的是key是否存在)

var twoSum = function(nums,target){
    let map = new Map();
    for(let i=0;i<nums.length;i++){
        let complement = target-nums[i];
        if(map.has(complement)){
            return [map.get(nums[complement]),i];
        }else{
            map.set(nums[i],i);
        }
    }
    return [];
}

 

 

3. 最长无重复子串(换成数组也一样)

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

 

示例 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 由英文字母、数字、符号和空格组成

 

思路:

1. 创建一个Set 和 两个指针,第一个 j 指针指向字符串的开头  第二个 i 随着 for 循环遍历字符串 

2. 如果set里没有s[i],说明目前为止还没有重复的字符,把s[i]添加到Set里,然后更新最大不重复字符的数量

3. 如果set里有s[i],则从set里开始删除s[j],并且递增j,再检查set里有没有s[i],如此反复直到set里没有s[i]为止(不能直接删除,因为要求最长无重复子串必须是连续的)

4. 重复步骤2和3,直到遍历完整个字符串

var lengthOfLongestSubstring = function(s){
        const set = new Set();
        let i=0,
            j=0,
            maxLength=0;
        if(s.length===0){
            return 0;
        }
        for(i;i<s.length;i++){
            if(!set.has(s[i])){
                set.add(s[i]);
                maxLength = Math.max(maxLength,set.size);
            }else{
                while(set.has(s[i])){
                    set.delete(s[j]);
                    j++;
                }
                set.add(s[i]);
            }
        }
        return maxLength;
}

 

 

88.合并两个有序数组

给你两个有序整数数组 nums1 和 nums2,请你将 nums2 合并到 nums1 中,使 nums1 成为一个有序数组。

初始化 nums1 和 nums2 的元素数量分别为 m 和 n 。你可以假设 nums1 的空间大小等于 m + n,这样它就有足够的空间保存来自 nums2 的元素。

 

示例 1:

输入:nums1 = [1,2,3,0,0,0], m = 3, nums2 = [2,5,6], n = 3
输出:[1,2,2,3,5,6]


示例 2:

输入:nums1 = [1], m = 1, nums2 = [], n = 0
输出:[1]

 

思路:

1. 定义两个尾指针分别指向 nums1 和 nums2 的尾部元素,再定义一个k指针指向num1的尾部

2. 从尾部元素开始遍历比较两个数组中元素的大小,较大的放在nums1的尾部

3. 当遍历完之后,若 nums2 中还有元素,则填充到nums1中

var merge = function(nums1, m, nums2, n) {
    let k = m+n-1;
    let i = m-1;
    let j = n-1;
    while(i>=0 && j>=0){
        if(nums1[i]>nums2[j]){
            // 利用后缀递减操作符进行递减操作
            nums1[k--] = nums1[i--];
        }else{
            nums1[k--] = nums2[j--];
        }
    }
    // j还没有走完
    while(j>=0){
        nums1[k--] = nums2[j--];
    }
    return nums1;
};

 

 

 

283. 移动零

给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。

示例:

输入: [0,1,0,3,12] 输出: [1,3,12,0,0] 说明:

必须在原数组上操作,不能拷贝额外的数组。 尽量减少操作次数。

 

思路:定义两个指针,快的指针遍历整个数组,遇到非零的数就赋值给慢的指针然后递增慢指针. 当遍历完整个数组之后,慢指针左边的数都为非0数。因此只需从慢指针开始,将数组后面的都赋值为0即可

var moveZeroes = function(nums){
    let left=0,right=0;
    while(right<nums.length){
        if(nums[right]!==0){
            nums[left]=nums[right];
            left++;
        }
        right++;
    }

    for(;left<nums.length;left++){
        nums[left]=0;
    }
}

 

344.反转字符串(不在刷题目录中)

编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 char[] 的形式给出。

不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。

你可以假设数组中的所有字符都是 ASCII 码表中的可打印字符。

 

示例 1:

输入:["h","e","l","l","o"] 输出:["o","l","l","e","h"] 示例 2:

输入:["H","a","n","n","a","h"] 输出:["h","a","n","n","a","H"]

 

思路: 很简单, 定义头尾指针, 逆向遍历,互换元素即可

var reserveString = function(s){
    let left=0,right=s.length-1;
    while(left<right){
        let temp = s[left];
        s[left]=s[right];
        s[right]=temp;
        i++;
        j--;
    }
    return s;
}

 

26. 删除有序数组中的重复项(不在刷题目录中)

给你一个有序数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。

不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。

示例 1:

输入:nums = [1,1,2] 输出:2, nums = [1,2] 解释:函数应该返回新的长度 2 ,并且原数组 nums 的前两个元素被修改为 1, 2 。不需要考虑数组中超出新长度后面的元素。 示例 2:

输入:nums = [0,0,1,1,1,2,2,3,3,4] 输出:5, nums = [0,1,2,3,4] 解释:函数应该返回新的长度 5 , 并且原数组 nums 的前五个元素被修改为 0, 1, 2, 3, 4 。不需要考虑数组中超出新长度后面的元素。

 

思路: 和283题移动零思路很像... 定义一个慢指针,一个快指针,用快指针遍历整个数组,遇到不等于慢指针的值,就赋值给慢指针加一对应的数值.

var removeDuplicates = function(nums) {
    let i=0,j=1;
    while(j<nums.length){
        if(nums[i]!==nums[j]){
             // 减少原地赋值的次数,比如原数组是[1,2,3,4,5],就会引起原地赋值
             if(j-i>1){  
                // 注意这里要先递增i的值再进行赋值
                nums[++i] = nums[j];
             }
        }
        j++;
    }
    return i+1;
}

 

485.最大连续1的个数

给定一个二进制数组, 计算其中最大连续 1 的个数。

示例:

输入:[1,1,0,1,1,1] 输出:3 解释:开头的两位和最后的三位都是连续 1 ,所以最大连续 1 的个数是 3.

提示:

输入的数组只包含 0 和 1 。 输入数组的长度是正整数,且不超过 10,000。

 

思路:定义两个变量maxCount和count, maxCount用来跟踪最大连续1个数,count用来计数每次遇到0之前1的个数

// 一次遍历法
var findMaxConsecutiveOnes = function(nums){
    let maxCount=0,count=0,n=nums.length;
    for(let i=0;i<n;i++){
        if(nums[i]==1){
            count++;
        }else{
            maxCount=Math.max(maxCount,count);
            count=0;
        }
    }
  // 这里要再算一次,因为当循环结束时, 最后一轮count的值可能不为0,需多进行一次比较 maxCount
= Math.max(maxCount,count); return maxCount; }

 

 

posted on 2021-05-31 16:37  BillGates--  阅读(136)  评论(0)    收藏  举报