hot100🔥踩点

Xayah,面试

哈希

1. 两数之和

class Solution {
public:
	vector<int> twoSum(vector<int>& nums, int target) {
	    unordered_map <int,int> hash;
	    for (int i=0;i<nums.size();i++) {
	        auto it = hash.find(target-nums[i]);
	        if (it!=hash.end()) {
	            return {it->second, i};
	        }
	        hash[nums[i]]=i;
	    }
	    return {};
	}
}

考察无序哈希表的使用,hash.find() 返回对应元素的迭代器,如果没有该元素则返回 hash.end()

49. 字母异位词分组

class Solution {
public:
    vector<vector<string>> groupAnagrams(vector<string>& strs) {
        unordered_map<string, vector<string>> mp;
        for (string s: strs) {
            string key=s;
            sort(key.begin(), key.end());
            mp[key].push_back(s);
        }
        vector<vector<string>> ans;
        for (auto [k,v]: mp) {
            ans.push_back(v);
        }
        return ans;
    }
};

128. 最长连续序列

class Solution {
public:
	int longestConsecutive(vector<int>& nums) {
	    unordered_set<int> st;
	    for(int num:nums) {
	        st.insert(num);
	    }
	    int ans=0;
	    for(int num:st) {
	        if(!st.count(num-1)) { // 从未出现过它的前一位,起始数字
	            int curLen=1;
	            int curNum=num;
	            while(st.count(curNum+1)) {
	                curLen++;
	                curNum+=1;
	            }
	            ans=max(ans,curLen);
	        }
	    }
	    return ans;
	}
};

283. 移动零

class Solution {
public:
    void moveZeroes(vector<int>& nums) {
	    int r=0, n=nums.size(); // r为最终数组里第一个0的下标
	    for (int l=0;l<n;l++) {
	        if (nums[l]!=0) {
	           swap(nums[l],nums[r]);
	           r++;
	        }
	    }
    }
};

11. 盛最多水得容器

class Solution {
public:
	int maxArea(vector<int> &height) {
	    int n=height.size();
	    int l=0, r=n-1;
	    while(l<r) {
	        ans=max(ans, (max(height[l], height[r]) * (r-l));
	        if (height[l]<height[r]) l++;
	        else r--;
	    }
	    return ans;
	}
}

15. 三数之和

class Solution {
public:
	vector<vector<int>> threeSum(vector<int>& nums) {
	    vector<vector<int>> res;
	    if(nums.size()<3) return res;
	    sort(nums.begin(),nums.end());
	    for(int i=0;i<nums.size();i++) {
	        // 新的一轮
	        if(nums[i]>0) break;
	        if(i>0 && nums[i]==nums[i-1]) continue; // 去重
	        int target=-nums[i];
	        int l=i+1,r=nums.size()-1;
	        while(l<r) {
	            if(nums[l]+nums[r]==target) {
	                res.push_back({nums[i],nums[l],nums[r]});
	                while(l<r && nums[l]==nums[l+1]) l++;
	                while(l<r && nums[r]==nums[r-1]) r--;
	                l++,r--;
	            }else if(nums[l]+nums[r]<target) {
	                l++;
	            }else r--;
	        }
	    }
	    return res;
	}
}

42. 接雨水

class Solution {
public:
	int trap(vector<int>& height) {
	    int n=height.size();
	    vector<int> left(n), right(n);
	    left[0]=height[0];
	    right[n-1]=height[n-1];
	    for (int i=1;i<n;i++) {
	        left[i]=max(left[i-1],height[i]);
	    }
	    for (int i=n-2;i>=0;i--) {
	        right[i]=max(right[i+1],height[i]);
	    }
	    int sum=0;
	    for (int i=0;i<n;i++) {
	        sum+=min(left[i],right[i])-height[i];
	    }
	    return sum;
	}
}

Left 数组代表当前位置之前的最大高度,Right 数组代表当前位置之后的最大高度,用来记录周围的最大高度!来减当前高度就能得到凹进去夺少啦!

3. 最长无重复字串

class Solution {
public:
	int lengthOfLongestSubstring(string s) {
	    unordered_set <char> mp;
	    int r=0, ans=0;
	    for (int l=0;l<s.size();l++) {
	        if (l>0) mp.erase(s[l-1]); // 重复的字符,在mp中去掉它
	        while (r<s.size() && !mp.count(s[r])) {
	            mp.insert(s[r]);
	            r++;
	        }
	        ans=max(ans, r-l);
	    }
	    return ans;
	}
}

哈希表 + 双指针

438. 找到字符串中所有字母异位词

转化成字母表,如果目标窗口数组和指定字母表数组相等则匹配成功

class Solution {
public:
	vector<int> findAnagrams(string s, string p) {
	    vector<int> sCount(26),pCount(26);
	    int ns=s.size(), np=p.size();
	    if (ns<np) return vector<int> {};
	    for (int i=0;i<np;i++) {
	       pCount[p[i]-'a']++; //填充指定字母表数组
	       sCount[s[i]-'a']++; //填充初始窗口数组
	    }
	    vector<int> ans;
	    if (pCount==sCount) ans.push_back(0);
	    for (int i=0;i<ns-np;i++) {
	        sCount[s[i]-'a']--;
	        sCount[s[i+np]-'a']++;
	        if(pCount==sCount) ans.push_back(i+1);
	    } 
	    return ans;
	}
}

560. 和为 k 的子数组

用哈希表记录前缀和

class Solution {
public: 
	int subarraySum(vector<int>& nums,int k) {
	    unordered_map<int,int> mp;
	    mp[0]=1;
	    int pre=0,count=0;
	    for (int x:nums) {
	        pre+=x;
	        if (mp.find(pre-k)!=mp.end()) {
	            count+=mp[pre-k];
	        }
	        mp[pre]++;
	    }
	    return count;
	}
}

239. 滑动窗口最大值

用优先队列 priority_queue<pair<int,int>> q{val, index} 作为滑动窗口

class Solution {
public:
	vector<int> maxSlidingWindow(vector<int>& nums, int k) {
	    int n=nums.size();
	    priority_queue<pair<int,int>> q; // {val, index}
	    for(int i=0;i<k;i++) { // 初始化填充窗口
	        q.push({nums[i],i});
	    }
	    vector<int> res;
	    res.push_back(q.top().first);
	    for(int i=k;i<n;i++) { // 移动窗口!
	        q.push({nums[i],i});
	        while(q.top().second<=i-k) { // 当前队头元素已经不在滑动窗口里咯!删掉删掉
	            q.pop();
	        }
	        res.push_back(q.top().first); // 添加当前窗口里的最大值进答案数组
	    }
	    return res;
	}
}

76. 最小覆盖子串 🔥

双指针,做两个判断

class Solution {
public:
	string minWindow(string s, string t) {
	    unordered_map<char,int> need, window; // 固定值和移动窗口
	    for (char x:t) {
	        need[x]++; // 填充固定值
	    }
	    int left=0, right=0; // 左右指针
	    int valid=0; // 满足的字符个数
	    int start=0, len=INT_MAX;
	    while(right<s.size()) {
	        // 取值判断移动右指针
	        char c=s[right];
	        right++;
	        if (need.count(c)) {
	            window[c]++;
	            if(window[c]==need[c]) { // 如果和目标的字符数一样则++
	                valid++;
	            }
	        }
	        while(valid==need.size()) { // 如果字符数和需求的一样了则左移指针
	            // 此处判断值
	            if (right-left<len) {
	                start=left;
	                len=right-left;
	            }
	            // 取值判断移动左指针
	            char d=s[left];
	            left++;
	            if (need.count(d)) {
	                if (window[d]==need[d]) {
	                    valid--;
	                }
	                window[d]--;
	            }
	        }
	    }
	    return len==INT_MAX?"":s.substr(start,len);
	}
}

53. 最大子段和

动态规划:

class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        int n=nums.size(), ans=0;
        vector<int> dp(n);
        dp[0]=nums[0];
        ans=dp[0];
        for (int i=1;i<n;i++) {
            dp[i]=max(dp[i-1]+nums[i], nums[i]);
            ans=max(ans,dp[i]);
        }
        return ans;
    }
}
© Xayah.RSS