leetcode刷题--200403

2020.4.3 LeetCode刷题记录


目录

1. 两数之和

解题:

2. 无重复字符的最长子串

解题:

3. 盛最多水的容器

解释:

4. 搜索旋转排序数组

         解析:

5. 删除排序数组中的重复项

题解:

1. 两数之和

题目链接:https://leetcode-cn.com/problems/two-sum/

标签:哈希表,数组

难度:简单

题目描述:

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

你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。

示例:

给定 nums = [2, 7, 11, 15], target = 9

因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]

解题:

用一个哈希表

class Solution {
public:
    vector twoSum(vector& nums, int target) {
        unordered_map  hash;
        vector  res;
        for(int i=0;i

2. 无重复字符的最长子串

题目链接:https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/

标签:哈希表,双指针

难度:中等

题目描述:

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

示例 1:

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

示例 2:

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

示例 3:

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

解题:

class Solution {
public:
    int lengthOfLongestSubstring(string s) { 
        int max=0;
        unordered_map hash;  //记录当前的子字符串各个字母出现的次数
        int n = s.size();
        for(int i=0,j=0;j1){
                hash[s[i++]]--;  //i右移
            }
            if(j-i+1>max)
                max = j-i+1;
        }
        return max;
    }
};

3. 盛最多水的容器

题目链接:https://leetcode-cn.com/problems/container-with-most-water/

标签:数组,双指针

难度:中等

题目描述:

给你 n 个非负整数 a1,a2,...,an,每个数代表坐标中的一个点 (i, ai) 。在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0)。找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。

说明:你不能倾斜容器,且 n 的值至少为 2。

图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为 49。

示例:

输入:[1,8,6,2,5,4,8,3,7]
输出:49

解释:

用双指针,一个从前,一个从后,遍历数组。

不管最终的答案是什么,所求的面积一定是两个点的横坐标差*纵坐标,并且纵坐标一定要选择两者中小的那个才能保证装进去水之后不漏出来。

当遍历两个点,假设横坐标为left和right,left的纵坐标比right纵坐标小,那一定选择left的纵坐标作为面积的高度,这时候如果想得到更大的面积,一定是移动left继续往左遍历。因为双指针遍历本身就是横坐标之差不断减小的过程,面积想要变更大,只能是纵坐标变大,当left的纵坐标

当left的纵坐标大于right的纵坐标时,更新right。

循环结束条件是left==right

class Solution {
public:
    int maxArea(vector& height) {
        int left=0;
        int right = height.size()-1;
        int res = 0;
        while (left

 

4. 搜索旋转排序数组

题目链接:https://leetcode-cn.com/problems/search-in-rotated-sorted-array/

难度: 中等

题目标签:二分查找

题目描述:

假设按照升序排序的数组在预先未知的某个点上进行了旋转。

( 例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] )。

搜索一个给定的目标值,如果数组中存在这个目标值,则返回它的索引,否则返回 -1 。

你可以假设数组中不存在重复的元素。你的算法时间复杂度必须是 O(log n) 级别

示例 1:

输入: nums = [4,5,6,7,0,1,2], target = 0
输出: 4

示例 2:

输入: nums = [4,5,6,7,0,1,2], target = 3

输出: -1

解析:

旋转数组二分,假设当前分割点mid为中间的数,

1. 如果当前的mid比最右边的right小,说明mid到right一定没有发生旋转数组,是有序的,这时先在右半边查找。所以这时,寻找target,如果target在mid到right之间,则更新left= mid,在数组的后半段去寻找target。否则,让right= mid-1;

2. 如果mid 不小于 right ,说明后半段有发生旋转的部分,此时先在左半边找,因为左边是有序的。如果target在左半边,那right= mid-1,否则就是让left= mid。

3. 循环结束时,一定是left= right

不管找没找到target,只要left==target,循环就会结束,

所以要判断循环结束时的nums[right]是否等于target,如果等于就返回right,否则返回-1

class Solution {
public:
    int search(vector& nums, int target) {
        if (nums.size()==0) return -1;
        int left = 0;
        int right = nums.size()-1;
        int mid = -1;
        while(left

5. 删除排序数组中的重复项

题目链接:https://leetcode-cn.com/problems/remove-duplicates-from-sorted-array/

难度:简单

题目标签:同向双指针

题目描述:

给定一个排序数组,你需要在 原地 删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。

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

示例 1:

给定数组 nums = [1,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。

你不需要考虑数组中超出新长度后面的元素。

说明:

为什么返回数值是整数,但输出的答案是数组呢?请注意,输入数组是以「引用」方式传递的,这意味着在函数里修改输入数组对于调用者是可见的。你可以想象内部操作如下:

// nums 是以“引用”方式传递的。也就是说,不对实参做任何拷贝
int len = removeDuplicates(nums);

// 在函数里修改输入数组对于调用者是可见的。
// 根据你的函数返回的长度, 它会打印出数组中该长度范围内的所有元素。
for (int i = 0; i < len; i++) {
    print(nums[i]);
}

题解:

数组完成排序后,我们可以放置两个指针 i和 j,其中 i是慢指针,而 j是快指针。

只要 nums[i] == nums[j],我们就增加 j 以跳过重复项。

当我们遇到 nums[j]不等于nums[i] 时,跳过重复项的运行已经结束,因此我们必须把它(nums[j])的值复制到 nums[i + 1]。然后递增 i,接着我们将再次重复相同的过程,直到 j 到达数组的末尾为止。

class Solution {
public:
    int removeDuplicates(vector& nums) {
        //two pointers,一个遍历数组,一个存储不重复的数
        //有序数组,重复的数必定挨着
        //判定是否重复数,只要判断和前一个数是否相同
        if(nums.empty()) return 0;

        int i = 0;
        for (int j = 1; j < nums.size(); j++) {
            if (nums[j] != nums[i]) {
                i++;
                nums[i] = nums[j];
            }
        }
        return i + 1;
    }
};

 

你可能感兴趣的:(3.,LeetCode刷题)