赞
踩
记录朋友们与我遇到的手撕代码题和实战题。
读取数字。
int a;
float b;
scanf("%d %f", &a, &b);
//
cin >> a >> b;
读取带空格的字符串。
string s;
getline(cin, s);
读取直到换行符之前的值。
vector<int> v;
while (cin.peek() != '\n') {
int t;
cin >> t;
v.emplace_back(move(t));
}
输出printf或者cout
printf("outoput : %d.\n", a);
cout << a;
使用cin.peek()函数
while (cin.peek() != '\n') {
int tmp;
cin >> tmp;
nums.push_back(tmp);
}
cin.ignore();
或者这种方式也可以,但是我用vscode不好用。
while (1) {
int tmp;
cin >> tmp;
nums.push_back(tmp);
while (getchar() == '\n') break;
}
bool jump(vector<int>& nums) {
int n = nums.size();
int step = 0;
int maxP - 0; // 下一step能够到达最远的距离
int end = 0; // 每一step能够到达最远的距离
for (int i = 0; i < n; ++i) {
mP = min(n - 1, max(mP, i + nums[i]));
if (i == 0) end = mP;
else if (i == end) {
end = mP;
step++;
}
}
return step;
}
vector<vector<int>> threeSum(vector<int>& nums) { sort(nums.begin(), nums.end()); int n = nums.size(); vector<vector<int>> ans; for (int i = 0; i < n; ++i) { while (i > 0 && i <= n - 2 && nums[i] == nums[i - 1]) i++; auto result = twosum(nums, i + 1, n - 1, -nums[i]); ans.insert(ans.end(), result.begin(), result.end()); } return ans; } vector<vector<int>> twosum(vector<int>& nums, int start, int end, int target) { vector<vector<int>> ans; if (end <= start) return ans; int sum = 0; while (start < end) { sum = nums[start] + nums[end]; if (sum == target) { vector<int> tmp; tmp.push_back(-target); tmp.push_back(nums[start]); tmp.push_back(nums[end]); ans.push_back(tmp); while (start < end && nums[start] == nums[start + 1]) start++; start++; while (start < end && nums[end] == nums[end - 1]) end--; end--; } else if (sum < target) start++; else end--; } return ans; }
int shipWithinDays(vector<int>& weights, int days) { int n = weights.size(), r = 0, l = 0, m = 0; for (int i = 0; i < n; ++i) { r += weights[i]; l = max(l, weights[i]); } while (l <= r) { m = (l + r) / 2; int need = 1, cur = 0; for (int w : weights) { if (cur + w > m) { need++; cur = w; } else cur += w; } if (need > days) l = m + 1; else r = m - 1; } return l; }
给出M条旅游线路,一行给出M个线路的起始日期,另一行给出M个线路的终止日期。输出有多少种满足有3条旅游地的方案。
比如4条线路,分别为:
5 1 3 2
7 2 4 4
输出为1,因为只有一条线路满足3个旅游地:
[1,2] - [3,4] - [5,7]
这一题是明显的回溯算法题,通过不断增加新的旅游地,判断是否满足各个旅游地起始终止日期不发生重叠。
原题是包含重复元素的实战题。我先从不含重复元素的开始整理。
void getans(vector<int>& nums, vector<vector<int>>& ans, const int len, int s1){ if (s1 == len) { for (const int i: nums) cout << i << " "; cout << endl; ans.emplace_back(nums); return; } for (int i = s1; i < len; ++i) { swap(nums[i], nums[s1]); getans(nums, ans, len, s1 + 1); swap(nums[i], nums[s1]); } } vector<vector<int>> permute(vector<int>& nums) { int n = nums.size(); if (n == 1) return vector<vector<int>>{nums}; vector<vector<int>> ans; getans(nums, ans, n, 0); return ans; }
如果是含重复元素的全排列问题,在排序后应该会处于相邻的位置,此时只需要判断相邻是否一样即可。
void getans(vector<int>& nums, vector<vector<int>>& ans, const int len, int s1){ if (s1 == len) { for (const int i: nums) cout << i << " "; cout << endl; ans.emplace_back(nums); return; } set<int> s; for (int i = s1; i < len; ++i) { if (i > s1 && nums[s1] == nums[i]) continue; // 避免相邻的相同 if (s.find(nums[i]) != s.end()) continue; // 避免待交换的相同 s.insert(nums[i]); // 避免以后出现相同的 swap(nums[s1], nums[i]); getans(nums, ans, len, s1 + 1); swap(nums[s1], nums[i]); } }
我在集度面试的时候也遇到了,而且额外要求输出是字典序,所以需要再sort一遍。现整理如下。
class Solution { private: vector<vector<int> > ans; public: vector<vector<int> > permuteUnique(vector<int> &num) { sort(num.begin(), num.end()); int n = num.size(); backtracking(num, 0, n); sort(ans.begin(), ans.end()); return ans; } void backtracking(vector<int> &num, int idx, int n) { if (idx == n - 1) { ans.push_back(num); return; } backtracking(num, idx + 1, n); set<int> s; for (int i = idx; i < n; ++i) { if (num[idx] == num[i]) continue; if (s.find(num[i]) != s.end()) continue; s.insert(num[i]); swap(num[idx], num[i]); backtracking(num, idx + 1, n); swap(num[idx], num[i]); } } };
void bisection(vector<int> nums, int target) {
int l = 0, r = nums.size() - 1, mid = 0;
while (l <= r) {
mid = (l + r) / 2;
if (nums[mid] >= target) r = mid - 1;
else l = mid + 1;
}
cout << r << endl;
}
ListNode* removeDuplicateNodes(ListNode* head) { set<int> s; if (!head || !head->next) return head; ListNode* prev = head, *cur = head->next; s.insert(head->val); while (cur) { if (s.find(cur->val) != s.end()) { prev->next = cur->next; cur = cur->next; continue; } s.insert(cur->val); prev = cur; cur = cur->next; } return head; }
#include <iostream> #include <vector> using namespace std; int main() { string s = "dddbccbad"; int n = s.size(), l = 0, len = 0; vector<vector<bool>> dp(n, vector<bool>(n, false)); for (int i = 0; i < n; ++i) { for (int j = 0; j < n - i; ++j) { if (i == 0) dp[j][j] = true; else { if (s[i + j] == s[j] && (i == 1 || dp[j + 1][i + j - 1])) { dp[j][i + j] = true; if (i > len) { l = j; len = i + 1; } } } } } cout << s.substr(l, len); return 0; }
#define swap(x, y) do{x=x+y;y=x-y;x=x-y;}while(0)
这是朋友面试遇到的题目,是leetcode第76题,属于hard,特此记录一下。
string minWindow(string s, string t) { // count用来记录位数,之后遍历的时候遇到一个而且需要的话就减一个 // l r 双指针 // minl minlen 记录最短的下标起始和长度 // 注意minlen初始化长度为一个很大的值,是因为有可能没有满足要求的子串,通过这个较大值来判断是否有 int count = t.size(), l = 0, r = 0, minl = 0, minlen = s.size() + 1; vector<bool> exist(128, false); // 用来记录t中某个字母存不存在,也可以用哈希表来找 vector<int> need(128, 0); // 用来记录t中字母出现的次数,因为可能重复 for (char c : t) { need[t]++; exist[t] = true; } for (;r < s.size(); ++r) { // 开始双指针遍历 if (exist[s[r]]) { if (need[s[r]] > 0) count--; // 找到一个需要的字母 need[s[r]]--; // 不管需不需要,都提供了 while (count == 0) { if (minlen > r - l + 1) { // 更新最短字符串 minl = l; minlen = r - l + 1; } // 开始移动左指针 if (exist[s[l]]) need[s[l]]++; // 提供的少了1个 if (need[s[l]] > 0) count++; // 如果把l对应的字母拿掉,count就得+1个 l++; } } } if (minlen == s.size() + 1) return ""; // 每找到,返回空字符串 return s.substr(minl, minlen); }
两数之和的升级版。
vector<vector<int>> threeSum(vector<int>& nums) { int n = nums.size(); vector<vector<int>> ans; if (n < 3) return ans; for (int i = 0; i < n - 2; ++i) { // 固定住第1位 if (i > 0 && nums[i] == nums[i - 1]) continue; int target = -nums[i], r = n - 1; for (int l = i + 1; l < n - 1; ++l) { // 固定住第2位 if (l > i + 1 && nums[l] == nums[l - 1]) continue; while (l < r && nums[l] + nums[r] > target) r--; // 因为第2位固定住了,所以只能移动第3位 if (l == r) continue; // 有可能r退到l处了 if (nums[l] + nums[r] == target) ans.push_back({nums[i], nums[l], nums[r]}); } } return ans; }
Leetcode第11题。思想是双指针,总是移动矮的那根。
int maxArea(vector<int>& height) {
int n = height.size(), l = 0, r = n - 1, ans = (n - 1) * min(height[l], height[r]);
while (l < r) {
ans = height[l] < height[r] ?
max(ans, min(height[++l], height[r]) * (r - l)) : max(ans, min(height[l], height[--r]) * (r - l));
}
return ans;
}
封装,继承,多态。
封装,继承,多态。
move将一个左值强行转化为右值,通过右值引用使用该值,可以避免拷贝,提高效率。
常见应用场景:
1.移动构造函数
2.vector.emplace_back()
堆内存由程序员创建和释放,栈内存由编译器自动创建和释放。
堆频繁使用会产生大量碎片,使程序效率降低;栈由于是编译器管理则不会产生这个问题。
栈的内存地址向减小方向使用;堆的内存地址向增大方向使用。
函数调用层数过多,每调用一次,函数的参数、局部变量等信息就压一次栈;
局部静态变量体积过大。
一是增大栈空间;二是改用动态分配,使用堆(heap)而不是栈(stack)。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。