赞
踩
小知识点记录: 哈希表map[j]-- 当减少到0了 不意味着j这个key对应从哈希表中删除了,只不过是value变成0了,map.count(j) 查找的j是对应 key
题目1:判断链表是否有环
#include<bits/stdc++.h> using namespace std; struct ListNode{ int val; ListNode* next; ListNode():val(0),next(nullptr){} ListNode(int x):val(x),next(nullptr){} }; //写个类 class Solution{ public: /*bool hasCycle(ListNode* head){ if(head==nullptr || head->next==nullptr) return false; ListNode* slow=head; ListNode* fast=head->next; while(slow!=fast){ if(fast==nullptr || fast->next==nullptr) return false; slow=slow->next; fast=fast->next->next; } return true; } */ bool hasCycle(ListNode*head){ if(head==nullptr) return false; unordered_set<ListNode*> set; while(head){ if(set.count(head)) return true; set.insert(head); head=head->next; } return false; } }; int main(){ int M=5; ListNode* dump=new ListNode(); ListNode* head=dump; for(int i=1;i<=M;i++){ int temp; cin>>temp; head->next=new ListNode(temp); head=head->next; } head->next=nullptr; head=dump->next; /*Solution *p; cout<<p->hasCycle(head); */ Solution p; cout<<p.hasCycle(head); }
题目2:快速幂运算
class Solution { public : double myPow(double x, int n) { if(n==0) return 1; long N=n; //防止负数最大反转出错 if(N<0){ x=1/x; N=-N; } double result=1; while(N>0){ if(N%2==1) result*=x; N>>=1; x*=x; } return result; } };
题目3:反转链表
class Solution { public: ListNode* reverseList(ListNode* head) { ListNode* pre=nullptr; ListNode* curr=head; while(curr){ ListNode* temp=curr->next; curr->next=pre; pre=curr; curr=temp; } return pre; } }; //反转双向链表的话 public: ListNode* reverseList1(ListNode* head) { ListNode* prev = nullptr; ListNode* curr = head; while (curr) { ListNode* next = curr->next; //curr->front=next; 如果是反转双向链表的话 前指针指向原来的next指针就行了 curr->next = prev; prev = curr; curr = next; } //pre->front=nullptr; //不用加 我就是说下。 return prev; }
class Solution { public: ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) { ListNode* dump=new ListNode(); ListNode* temp=dump; while(l1!=nullptr && l2!=nullptr){ if(l1->val<l2->val){ temp->next=l1; l1=l1->next; temp=temp->next; } else{ temp->next=l2; l2=l2->next; temp=temp->next; } } temp->next= l1==nullptr ? l2:l1; return dump->next; } };
class Solution { public: //合并两个有续链表~ ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) { ListNode* dump=new ListNode(); ListNode* temp=dump; while(l1!=nullptr && l2!=nullptr){ if(l1->val<l2->val){ temp->next=l1; l1=l1->next; temp=temp->next; } else{ temp->next=l2; l2=l2->next; temp=temp->next; } } temp->next= l1==nullptr ? l2:l1; return dump->next; } //合并K个有序链表 ListNode* mergeKLists(vector<ListNode*>& lists) { ListNode *ans = nullptr; for (int i = 0; i < lists.size(); ++i) { ans = mergeTwoLists(ans, lists[i]); } return ans; } };
class Solution { public: int subarraySum(vector<int>& nums, int k) { unordered_map<int, int> mp; mp[0] = 1; int count = 0, pre = 0; for (auto& x:nums) { pre += x; if (mp.count(pre - k)==1) { count += mp[pre - k]; } mp[pre]++; } return count; } };
class Solution { public: bool checkSubarraySum(vector<int>& nums, int k) { int m = nums.size(); if (m < 2) { return false; } unordered_map<int, int> mp; mp[0] = -1; int remainder = 0; for (int i = 0; i < m; i++) { remainder = (remainder + nums[i]) % k; if (mp.count(remainder)) { /如果前面的前缀和 和后面这个弄下来的余数相同,说明后面这一段 被K整除! int prevIndex = mp[remainder]; if (i - prevIndex >= 2) { return true; } } else mp[remainder] = i; // key=前缀和,value=索引 注意到只有没出现才会更新下标,所以保证最左下标,所以else必不可少!!! } return false; } };
class Solution { public: vector<int> getLeastNumbers(vector<int>& arr, int k) { vector<int> vec(k, 0); if (k == 0) { // 排除 0 的情况 return vec; } priority_queue<int> Q; for (int i = 0; i < k; ++i) { Q.push(arr[i]); } for (int i = k; i < (int)arr.size(); ++i) { if (Q.top() > arr[i]) { Q.pop(); Q.push(arr[i]); } } for (int i = 0; i < k; ++i) { vec[i] = Q.top(); Q.pop(); } return vec; } };
class Solution { public: int getKthMagicNumber(int k) { priority_queue<long, vector<long>, greater<long>> pq; pq.push(1); long res; while (k > 0) { res = pq.top(); pq.pop(); while (!pq.empty() && res == pq.top()) pq.pop(); pq.push(res * 3); pq.push(res * 5); pq.push(res * 7); k--; } return res; } };
class Solution { public: int longestCommonSubsequence(string text1, string text2) { int m = text1.length(), n = text2.length(); vector<vector<int>> dp(m + 1, vector<int>(n + 1)); for (int i = 1; i <= m; i++) { char c1 = text1.at(i - 1); //at返回下标为i-1 for (int j = 1; j <= n; j++) { char c2 = text2[j-1]; if (c1 == c2) { dp[i][j] = dp[i - 1][j - 1] + 1; } else { dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]); } } } return dp[m][n]; } };
class Solution { public: int lengthOfLongestSubstring(string s) { unordered_map<char, int> window; int left = 0, right = 0; int res = 0; // 记录结果 while (right < s.size()) { char c = s[right]; right++; // 进行窗口内数据的一系列更新 window[c]++; // 判断左侧窗口是否要收缩 while (window[c] > 1) { char d = s[left]; left++; // 进行窗口内数据的一系列更新 window[d]--; } // 在这里更新答案 res = max(res, right - left); } return res; };
class Solution { public: vector<vector<int>> threeSum(vector<int>& nums) { int n = nums.size(); sort(nums.begin(), nums.end()); vector<vector<int>> ans; for (int first = 0; first <n-2; ++first) { // 需要和上一次枚举的数不相同 用一次就行了 if (first > 0 && nums[first] == nums[first - 1]) { continue; } //进入双指针环节 int target = -nums[first]; int second = first + 1; int third = n - 1; while(second<third) { if(nums[second] + nums[third]==target){ ans.push_back({nums[first], nums[second], nums[third]}); while(second<third && nums[second] == nums[++second]);//去重 while(second<third && nums[third] == nums[--third]); } else if(nums[second] + nums[third] > target){ while(second<third && nums[third] == nums[--third]); } else if(nums[second] + nums[third] < target){ while(second<third && nums[second] == nums[++second]); } } } return ans; } };
class Solution { public: //中心扩展对称即是回文串,在这基础上用双指针 string longestPalindrome(string s) { int n=s.size(); string res; for(int i=0;i<n;i++){ string s1=palindrome(s,i,i); string s2=palindrome(s,i,i+1); res=res.size()>s1.size() ? res:s1; res=res.size()>s2.size() ? res:s2; } return res; } //调用辅助函数 string palindrome(string & s, int l,int r){ while(l>=0 && r<s.size() && s[l]==s[r]){ l--;r++; } return s.substr(l+1,r-l-1); } };
class Solution { public: int countSubstrings(string s) { int num = 0; int n = s.size(); for(int i=0;i<n;i++)//遍历回文中心点 { for(int j=0;j<=1;j++)//j=0,中心是一个点,j=1,中心是两个点 { int l = i; int r = i+j; while(l>=0 && r<n && s[l--]==s[r++])num++; } } return num; } };
class Solution { private: vector<vector<int>> f; vector<vector<string>> ret; vector<string> ans; int n; public: void dfs(const string& s, int i) { if (i == n) { ret.push_back(ans); return; } for (int j = i; j < n; ++j) { //探索同一个i下不同的j的组合 if (f[i][j]) { ans.push_back(s.substr(i, j - i + 1)); dfs(s, j + 1); //继续探索当前i往后走的新开始 ans.pop_back(); } } } vector<vector<string>> partition(string s) { n = s.size(); f.assign(n, vector<int>(n, true)); for (int i = n - 1; i >= 0; --i) { for (int j = i + 1; j < n; ++j) { f[i][j] = (s[i] == s[j]) && f[i + 1][j - 1]; } } dfs(s, 0); return ret; } };
class Solution { vector<int> vis; vector<int>perm; vector<vector<int>>ans; public: void backtrack(vector<int>& nums) { if(perm.size()==nums.size()){ ans.emplace_back(perm); return; } for(int i=0; i<nums.size();i++){ if(vis[i] ||(i>0 && nums[i]==nums[i-1] && !vis[i-1])) continue; vis[i]=1; perm.emplace_back(nums[i]); backtrack(nums); perm.pop_back(); vis[i]=0; } } //进入主函数 vector<vector<int>> permuteUnique(vector<int>& nums) { vis.resize(nums.size()); sort(nums.begin(),nums.end()); backtrack(nums);//一开始肯定对第0个元素操作 return ans; } };
class Solution { vector<int> vis; vector<int> track; vector<vector<int>> res; public: void backtrack(vector<int> &Num) { if(track.size()==Num.size()){ res.push_back(track); return; } for(int i=0; i<Num.size();i++){ if(vis[i]) continue; vis[i]=1; track.push_back(Num[i]); backtrack(Num); track.pop_back(); vis[i]=0; } } vector<vector<int>> permute(vector<int>& nums) { vis.resize(nums.size()); backtrack(nums); return res; } };
class Solution { public: string longestCommonPrefix(vector<string>& strs) { if (!strs.size()) { return ""; } string prefix = strs[0]; int count = strs.size(); for (int i = 1; i < count; ++i) { prefix = longestCommonPrefix(prefix, strs[i]); if (!prefix.size()) //如果前缀为0,提前退出了 break; } return prefix; } string longestCommonPrefix(const string& str1, const string& str2) { int length = min(str1.size(), str2.size()); int index = 0; while (index < length && str1[index] == str2[index]) { ++index; } return str1.substr(0, index); //从0开始index个 } };
class CQueue { stack<int> stack1,stack2; //私有变量 也是全局把可以理解为 public: //三个函数 初始化、入栈和出栈 CQueue() { //初始化清空栈 while (!stack1.empty()) { stack1.pop(); } while (!stack2.empty()) { stack2.pop(); } } void appendTail(int value) { stack1.push(value); //入栈 } int deleteHead() { //出栈函数 // 如果第二个栈为空 if (stack2.empty()) { while (!stack1.empty()) { stack2.push(stack1.top()); stack1.pop(); } } if (stack2.empty()) { return -1; } else { int deleteItem = stack2.top(); stack2.pop(); return deleteItem; } } };
class Solution { vector<vector<int>> ans; vector<int> combine; public: void dfs(vector<int>& candidates, int target, int idx) { if (idx == candidates.size()) { //记录枚举位置 return; } if (target == 0) { ans.emplace_back(combine); return; } // 要么直接跳过,枚举下个 dfs(candidates, target,idx + 1); // 要么选择当前数 不跳过 //选择的时候如果这个数很大了,那就没啥路走了结束 其实就是无法选择 这个分支结束而已。 if (target - candidates[idx] >= 0) { combine.emplace_back(candidates[idx]); dfs(candidates, target - candidates[idx],idx); combine.pop_back(); } } vector<vector<int>> combinationSum(vector<int>& candidates, int target) { dfs(candidates, target, 0); return ans; } };
优化方法:
class Solution { vector<vector<int>> ans; vector<int> combine; public: void dfs(vector<int>& candidates, int target, int idx) { if(target<0) return; if (target == 0) { ans.emplace_back(combine); return; } for (int i = idx; i < candidates.size(); i++){ //每一层可以继续选择当前元素 target-=candidates[i]; combine.emplace_back(candidates[i]); dfs(candidates, target,i); target+=candidates[i]; combine.pop_back(); } } vector<vector<int>> combinationSum(vector<int>& candidates, int target) { dfs(candidates, target, 0); return ans; } };
class Solution { private: vector<vector<int>> result; vector<int> path; vector<bool> used; void backtracking(vector<int>& candidates, int target,int startIndex) { if(target<0) return; if (target==0) { result.push_back(path); return; } //这里的for是给了他不同的起点。 就是说不走回头路,往后走 for (int i = startIndex; i < candidates.size(); i++) { // used[i - 1] == true,说明同一树支candidates[i - 1]使用过 // used[i - 1] == false,说明同一树层candidates[i - 1]使用过 // 要对同一树层使用过的元素进行跳过 if (i > 0 && candidates[i] == candidates[i - 1] && used[i - 1] == false) { continue; } target -= candidates[i]; path.push_back(candidates[i]); used[i] = true; backtracking(candidates, target,i + 1); // 和39.组合总和的区别1,这里是i+1,每个数字在每个组合中只能使用一次 used[i] = false; target += candidates[i]; path.pop_back(); } } public: vector<vector<int>> combinationSum2(vector<int>& candidates, int target) { used.resize(candidates.size(),false); path.clear(); result.clear(); // 首先把给candidates排序,让其相同的元素都挨在一起。 sort(candidates.begin(), candidates.end()); backtracking(candidates, target,0); return result; } };
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
unordered_map<int, int> hashtable;
for (int i = 0; i < nums.size(); ++i) {
if (hashtable.count(target-nums[i]))
return {hashtable[target-nums[i]], i};
hashtable[nums[i]] = i;
}
return {};
}
};
class Solution { public: ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) { ListNode *head = nullptr, *tail = nullptr; int carry = 0; while (l1 || l2) { int n1 = l1 ? l1->val: 0; int n2 = l2 ? l2->val: 0; int sum = n1 + n2 + carry; if (!head) { head = tail = new ListNode(sum % 10); } else { tail->next = new ListNode(sum % 10); tail = tail->next; } carry = sum / 10; if (l1) { l1 = l1->next; } if (l2) { l2 = l2->next; } } if (carry > 0) { tail->next = new ListNode(carry); } return head; } };
class Solution { public: ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) { return addTwoNumbersCore(l1, l2, 0); } ListNode* addTwoNumbersCore(ListNode* l1, ListNode* l2, int carry) { if (!l1 && !l2 && carry == 0) { // 当输入的节点均为null且无需处理进位时,结束 return nullptr; } int val = carry + (l1 ? l1 -> val : 0) + (l2 ? l2 -> val : 0); // 计算当前的和 ListNode* res = new ListNode(val % 10); res -> next = addTwoNumbersCore((l1 ? l1 -> next : nullptr), (l2 ? l2 -> next : nullptr), val / 10); return res; } };
题目20:二叉树的最大深度
class Solution {
public:
int maxDepth(TreeNode* root) {
if (root == nullptr) return 0;
return max(maxDepth(root->left), maxDepth(root->right)) + 1;
}
};
class Solution { public: int height(TreeNode* root) { if (root == NULL) { return 0; } else { return max(height(root->left), height(root->right)) + 1; } } bool isBalanced(TreeNode* root) { if (root == NULL) { return true; } else { return abs(height(root->left) - height(root->right)) <= 1 && isBalanced(root->left) && isBalanced(root->right); } } };
class Solution { public: void construct_paths(TreeNode* root, string path, vector<string>& paths) { if (root != nullptr) { path += to_string(root->val); if (root->left == nullptr && root->right == nullptr) { // 当前节点是叶子节点 paths.push_back(path); // 把路径加入到答案中 } else { path += "->"; // 当前节点不是叶子节点,继续递归遍历 construct_paths(root->left, path, paths); construct_paths(root->right, path, paths); } } } vector<string> binaryTreePaths(TreeNode* root) { vector<string> paths; construct_paths(root, "", paths); return paths; } };
class Solution {
public:
bool isSymmetric(TreeNode* root) {
if(root==nullptr) return true;
return recur(root->left,root->right);
}
bool recur(TreeNode* root1, TreeNode* root2){
if(!root1 && !root2) return true;
if(!root1 || !root2 ||root1->val!=root2->val) return false;
return recur(root1->left,root2->right) && recur(root1->right,root2->left);
}
};
class Solution {
public:
TreeNode* mirrorTree(TreeNode* root) {
if (root == nullptr) {
return nullptr;
}
TreeNode* left = mirrorTree(root->left);
TreeNode* right = mirrorTree(root->right);
root->left = right;
root->right = left;
return root;
}
};
class Solution { public: bool isPalindrome(int x) { // 特殊情况: // 如上所述,当 x < 0 时,x 不是回文数。 // 同样地,如果数字的最后一位是 0,为了使该数字为回文, // 则其第一位数字也应该是 0 // 只有 0 满足这一属性 if (x < 0 || (x % 10 == 0 && x != 0)) { return false; } int revertedNumber = 0; while (x > revertedNumber) { revertedNumber = revertedNumber * 10 + x % 10; x /= 10; } // 当数字长度为奇数时,我们可以通过 revertedNumber/10 去除处于中位的数字。 // 例如,当输入为 12321 时,在 while 循环的末尾我们可以得到 x = 12,revertedNumber = 123, // 由于处于中位的数字不影响回文(它总是与自己相等),所以我们可以简单地将其去除。 return x == revertedNumber || x == revertedNumber / 10; } };
class Solution { public: bool isPalindrome(int x) { string s=to_string(x); int n=s.size(); int left=0,right=n-1; while(left<right){ if(s[left]==s[right]){ left++;right--; } else return false; } return true; } };
class Solution { public: int reverse(int x) { long long r = 0; while (x) { r = r * 10 + x % 10; x /= 10; } if (abs(r) > INT_MAX) return 0; return r; } }; ```cpp class Solution { public: int reverse(int x) { int r = 0; while (x) { if (r > 0 && r > (INT_MAX - x % 10) / 10) return 0; if (r < 0 && r < (INT_MIN - x % 10) / 10) return 0; r = r * 10 + x % 10; x /= 10; } return r; } };
class Solution { public: string convert(string s, int numRows) { if (numRows == 1) return s; vector<string> rows(min(numRows, int(s.size()))); int curRow = 0; bool goingDown = false; for (char c : s) { rows[curRow] += c; if (curRow == 0 || curRow == numRows - 1) goingDown = !goingDown; curRow += goingDown ? 1 : -1; } string ret; for (string row : rows) ret += row; return ret; } };
class Solution {
public:
bool findNumberIn2DArray(vector<vector<int>>& matrix, int target) {
int i = matrix.size() - 1, j = 0;
while(i >= 0 && j < matrix[0].size())
{
if(matrix[i][j] > target) i--;
else if(matrix[i][j] < target) j++;
else return true;
}
return false;
}
};
class Solution {
public:
int maxSubArray(vector<int>& nums) {
int pre = 0, maxAns = nums[0];
for (const auto &x: nums) {
pre = max(pre + x, x);
maxAns = max(maxAns, pre);
}
return maxAns;
}
};
class Solution { public: TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) { //很明显此题需要递归 return newtree(preorder,0,preorder.size()-1,inorder,0,inorder.size()-1); } //构造调用函数 TreeNode* newtree(vector<int>& preorder,int l1,int r1, vector<int>& inorder,int l2,int r2){ if(l1>r1) return nullptr; TreeNode* root=new TreeNode(); root->val=preorder[l1]; //要找到根节点在中序遍历中的位置 int index=0;int length=0; for(int i=l2;i<=r2;i++){ if(inorder[i]==root->val){ index=i; length=index-l2; break; } } //构建左右子树 root->left=newtree(preorder,l1+1,l1+length,inorder,l2,index-1); root->right=newtree(preorder,l1+length+1,r1,inorder,index+1,r2); return root; } };
class Solution { public: int longestPalindrome(string s) { unordered_map<char, int> count; int ans = 0; for (char c : s) ++count[c]; for (auto p : count) { int v = p.second; ans += v / 2 * 2; if (v % 2 == 1 and ans % 2 == 0) ++ans; } return ans; } };
利用 stringstream 把字符串s 转化为输入流 此时我们自定义的ssin就可以向cin一样去使用
我们自定义的ssin和cin一样, 每次读取时都会跳过空格
class Solution {
public:
string reverseWords(string s) {
string s1[1000], s2;
int i = 0;
stringstream ssin(s);
while(ssin>>s1[i])
i++;
for(int j = i - 1; j > 0; j--)
s2+=s1[j]+" ";
s2+=s1[0];
return s2;
}
};
class Solution {
public:
void rotate(vector<int>& nums, int k) {
int n = nums.size();
vector<int> newArr(n);
for (int i = 0; i < n; ++i) {
newArr[(i + k) % n] = nums[i]; //比如数组有8位,这个8就放到开头的地方~
}
nums.assign(newArr.begin(), newArr.end());//容器赋值运算,将new中的值送给nums
};
方法2,用o(1)的空间复杂度
https://leetcode-cn.com/problems/rotate-array/solution/xuan-zhuan-shu-zu-by-leetcode-solution-nipk/
class Solution { public: void reverse(vector<int>& nums, int start, int end) { while (start < end) { swap(nums[start], nums[end]); start += 1; end -= 1; } } void rotate(vector<int>& nums, int k) { k %= nums.size(); reverse(nums, 0, nums.size() - 1); reverse(nums, 0, k - 1); reverse(nums, k, nums.size() - 1); } };
class Solution { public: vector<vector<int>> ret; vector<int> path; void dfs(TreeNode* root, int targetSum) { if (root == nullptr) { return; } path.emplace_back(root->val); targetSum -= root->val; if (root->left == nullptr && root->right == nullptr && targetSum == 0) { ret.emplace_back(path); } dfs(root->left, targetSum); dfs(root->right, targetSum); path.pop_back(); } vector<vector<int>> pathSum(TreeNode* root, int targetSum) { dfs(root, targetSum); return ret; } };
class Solution {
public:
bool hasPathSum(TreeNode *root, int sum) {
if (root == nullptr) {
return false;
}
if (root->left == nullptr && root->right == nullptr) {
return sum == root->val;
}
return hasPathSum(root->left, sum - root->val) ||
hasPathSum(root->right, sum - root->val);
}
};
队列的解:
class Solution { public: bool hasPathSum(TreeNode *root, int sum) { if (root == nullptr) { return false; } queue<TreeNode *> que_node; queue<int> que_val; que_node.push(root); que_val.push(root->val); while (!que_node.empty()) { TreeNode *now = que_node.front(); int temp = que_val.front(); que_node.pop(); que_val.pop(); if (now->left == nullptr && now->right == nullptr) { if (temp == sum) { return true; } continue; } if (now->left != nullptr) { que_node.push(now->left); que_val.push(now->left->val + temp); } if (now->right != nullptr) { que_node.push(now->right); que_val.push(now->right->val + temp); } } return false; } };
class Solution { private: void helper(int i, int n, int k, vector<vector<int>>& ret, vector<int>& cur) { if (cur.size() == k) { ret.emplace_back(cur); return; } // i 超界 if (i > n) { return; } // 不加入 i helper(i + 1, n, k, ret, cur); // 加入 i cur.push_back(i); helper(i + 1, n, k, ret, cur); cur.pop_back(); } public: vector<vector<int>> combine(int n, int k) { vector<vector<int>> ret; vector<int> cur; helper(1, n, k, ret, cur); return ret; } };
class Solution { public: ListNode *detectCycle(ListNode *head) { ListNode *fast = head, *slow = head; while (true) { if (fast == nullptr || fast->next == nullptr) return nullptr; fast = fast->next->next; slow = slow->next; if (fast == slow) break; } fast = head; while (slow != fast) { slow = slow->next; fast = fast->next; } return fast; } };
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。