5月31日刷题笔记——数组、字符串、链表
题目1:73. 矩阵置零(中等题)
知识点:数组、(哈希表)
我的题解:
暴力题解。
class Solution {
public:
void setZeroes(vector<vector<int>>& matrix) {
int m = matrix.size();
int n = matrix[0].size();
int i = 0;
int j = 0;
int k = m;
unordered_map<int, int> zero;
for(i = 0; i < m; i++){
for(j = 0; j < n; j++){
if(matrix[i][j] == 0){
if(zero.count(i)){
zero[k] = j;
k++;
}else{
zero[i] = j;
}
}
}
}
for(i = 0; i < m; i++){
for(auto num:zero){
matrix[i][num.second] = 0;
}
}
for(i = 0; i < n; i++){
for(auto num:zero){
if(num.first < m){
matrix[num.first][i] = 0;
}
}
}
}
};
题目2:387. 字符串中的第一个唯一字符(简单题)
知识点:字符串
我的题解:
class Solution {
public:
int firstUniqChar(string s) {
unordered_map<char, int> str;
for(auto ch:s){
str[ch]++;
}
for(int i = 0; i < s.size(); i++){
// 看了题解想起来,这个count不需要啦!
if(str.count(s[i]) && str[s[i]] == 1){
return i;
}
}
return -1;
}
};
题目3:383. 赎金信(简单题)
知识点:字符串
我的题解:
class Solution {
public:
bool canConstruct(string ransomNote, string magazine) {
if(ransomNote.size() > magazine.size()) return false;
unordered_map<char, int> str1;
unordered_map<char, int> str2;
for(auto s:ransomNote){
str1[s]++;
}
for(auto s:magazine){
str2[s]++;
}
for(auto s:ransomNote){
if(str1[s] > str2[s]) return false;
}
return true;
}
};
根据题解的思路发现刻意少一次循环,复现代码如下:
class Solution {
public:
bool canConstruct(string ransomNote, string magazine) {
if(ransomNote.size() > magazine.size()) return false;
unordered_map<char, int> str;
for(auto s:magazine){
str[s]++;
}
for(auto s:ransomNote){
str[s]--;
if(str[s] < 0) return false;
}
return true;
}
};
题目4:242. 有效的字母异位词(简单题)
知识点:字符串
我的题解:
这题跟上一题赎金信的思路其实是一样的, 根据上一题的思路,用两个循环实现。
class Solution {
public:
bool isAnagram(string s, string t) {
if(s.size() != t.size()) return false;
unordered_map<char, int> str;
for(auto ch:t){
str[ch]++;
}
for(auto ch:s){
str[ch]--;
if(str[ch] < 0) return false;
}
return true;
}
};
看了题解,还有更方便的思路,就是直接排序,相同就ok。根据题解复现代码:
class Solution {
public:
bool isAnagram(string s, string t) {
if(s.size() != t.size()) return false;
sort(s.begin(),s.end());
sort(t.begin(),t.end());
return s == t;
}
};
题目5:141. 环形链表(简单题)
知识点:链表、哈希表、双指针
因为完全忘了链表了,所以不知道怎么下手,直接看题解。哈希表记录访问过的节点。重新访问一次就说明来过了。
其实看了题解发现是很简单的思路,但不知道是不是看到链表被唬住了,就是会觉得很难不会做。毛病要改呀!哎。
根据哈希表方式的题解复现代码:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
bool hasCycle(ListNode *head) {
unordered_set<ListNode *> set;
while(head != NULL){
// 注意这里比较的是对象,不是对象的值,所以就算链表内出现不同节点,相同的值也依然有效
if(set.count(head)) return true;
set.insert(head);
head = head->next;
}
return false;
}
};
方法二:快慢指针
思路:
代码如下:
class Solution {
public:
bool hasCycle(ListNode *head) {
ListNode* fast = head;
ListNode* slow = head;
while(fast != NULL && fast->next != NULL) {
slow = slow->next;
fast = fast->next->next;
// 快慢指针相遇,说明有环
if (slow == fast) return true;
}
return false;
}
};