————————
后记:没想到这么快就拿到了腾讯的暑期实习offer,所以把其他厂的面试全推了,这个打卡也就懒得继续了,直接弃坑…………
————————
一直刷hard不是什么好方法,决定改一下刷题的方式,刷下面链接里的常问题。
https://leetcode.com/problemset/top-interview-questions/
目录
287. Find the Duplicate Number
230. Kth Smallest Element in a BST
3. Longest Substring Without Repeating Characters
(未做)5. Longest Palindromic Substring
(好题)1371. Find the Longest Substring Containing Vowels in Even Counts
1372. Longest ZigZag Path in a Binary Tree
2020.03.07
287. Find the Duplicate Number
https://leetcode.com/problems/find-the-duplicate-number/
1到n,里面有一个数重复,给你n+1这样的数,求重复的那个数
首先想到,暴力排序是nlogn
然后思考O(n)做法,既然已知n,那么可以求出1-n的和是(n+1)*n/2,将数组sum减去这个数即可。
交了一发wa发现看错题目了QaQ,不是1到n的全排列,重复的那个数可以重复多次,但只有一个数重复
那就换个思路,归位法,从1开始,将a[i]放到他本来的位置上,比如第一个数是3,那就把第三个数和他对调,再继续。中间如果发现2个数相同,直接return。当然了,排序也是可取的,或者更秀一点拿个set或者哈希表存一下遇到重复即可。
Runtime: 8 ms, faster than 97.50% of C++ online submissions for Find the Duplicate Number.
Memory Usage: 9.1 MB, less than 100.00% of C++ online submissions for Find the Duplicate Number.
class Solution {
public:
int findDuplicate(vector<int>& nums) {
int n = nums.size();
for (int i = 0; i < n-1; i++) {
if (nums[i] == i + 1) continue;
if (nums[i] == nums[nums[i]-1]) return nums[i];
swap(nums[i], nums[nums[i]-1]);
i--;
}
return nums[n-1];
}
};
328. Odd Even Linked List
一个链表,就地把位奇数结点移到前面位偶数结点移到后面。不能修改值,只能修改next
第一思路,两个指针交错走,互相忽视对方,最后奇-next=偶开头
Runtime: 16 ms, faster than 92.72% of C++ online submissions for Odd Even Linked List.
Memory Usage: 10 MB, less than 8.57% of C++ online submissions for Odd Even Linked List.
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* oddEvenList(ListNode* head) {
ListNode* ans = head;
if (head == NULL || head->next == NULL || head->next->next == NULL) return ans;
ListNode *odd, *even, *tmp = head->next;
odd = head;
even = head->next;
while(odd->next && odd->next->next && even->next && even->next->next) {
odd->next = odd->next->next;
even->next = even->next->next;
odd = odd->next;
even = even->next;
}
if (even->next != NULL) {
odd->next = odd->next->next;
odd = odd->next;
even->next = NULL;
}
odd->next = tmp;
return ans;
}
};
230. Kth Smallest Element in a BST
求二叉搜索树的第k小元素,也就是中序遍历第k个数,没什么好说的。
Runtime: 16 ms, faster than 96.53% of C++ online submissions for Kth Smallest Element in a BST.
Memory Usage: 21 MB, less than 100.00% of C++ online submissions for Kth Smallest Element in a BST.
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
int kthSmallest(TreeNode* root, int k) {
int cur = 0, ans;
solve(root, k, cur, ans);
return ans;
}
void solve(TreeNode* root, int k, int& cur, int& ans) {
if (root->left) solve(root->left, k, cur, ans);
if (++cur == k) ans = root->val;
if (root->right) solve(root->right, k, cur, ans);
}
};
1. Two Sum
https://leetcode.com/problems/two-sum/
给你一个数组和一个targert,求里面是否有2个数的和等于target
首先想到暴力,直接排序nlogn再二分nlogn最后nlogn
然后,可以将数组转存为一个哈希表,表示x在数组里出现几次,然后再遍历即可。
Runtime: 16 ms, faster than 47.86% of C++ online submissions for Two Sum.
Memory Usage: 10.5 MB, less than 13.35% of C++ online submissions for Two Sum.
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
vector<int> ans;
map<int, int> m;
int n = nums.size();
for(int i = 0; i < n; i++) {
m[nums[i]]++;
}
for(int i = 0; i < n; i++) {
if (nums[i] == target-nums[i] && m[target-nums[i]] >= 2) {
ans.push_back(i);
for (int j = 0; j < n; j++) {
if (j != i && nums[j] == target-nums[i]) {
ans.push_back(j);
break;
}
}
break;
}
if (nums[i] != target-nums[i] && m[target-nums[i]] >= 1) {
ans.push_back(i);
for (int j = 0; j < n; j++) {
if (nums[j] == target-nums[i]) {
ans.push_back(j);
break;
}
}
break;
}
}
return ans;
}
};
2. Add Two Numbers
https://leetcode.com/problems/add-two-numbers/
两个链表,各存储一个数,直接用int求和当然可以,但是那只能限于n<10,显然不切实际,不可能用大数,只能用进位法模拟十进制加法。
Runtime: 28 ms, faster than 69.28% of C++ online submissions for Add Two Numbers.
Memory Usage: 10.7 MB, less than 5.14% of C++ online submissions for Add Two Numbers.
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
int p = l1->val + l2->val;
ListNode *head = new ListNode(p % 10);
ListNode *last = head;
l1 = l1->next;
l2 = l2->next;
while (l1 && l2) {
int q = l1->val + l2->val + (p > 9);
last->next = new ListNode(q % 10);
last = last->next;
p = q;
l1 = l1->next;
l2 = l2->next;
}
while (l1) {
int q = l1->val + (p > 9);
last->next = new ListNode(q % 10);
last = last->next;
p = q;
l1 = l1->next;
}
while (l2) {
int q = l2->val + (p > 9);
last->next = new ListNode(q % 10);
last = last->next;
p = q;
l2 = l2->next;
}
if (p > 9) {
last->next = new ListNode(1);
}
return head;
}
};
3. Longest Substring Without Repeating Characters
https://leetcode.com/problems/longest-substring-without-repeating-characters/
求字符串的最长子串,子串不包含重复字符。显然尺取,开l和r滚就好了。
Runtime: 80 ms, faster than 16.35% of C++ online submissions for Longest Substring Without Repeating Characters.
Memory Usage: 9.8 MB, less than 75.12% of C++ online submissions for Longest Substring Without Repeating Characters.
class Solution {
public:
int lengthOfLongestSubstring(string s) {
int n = s.length();
if (n == 0) return 0;
int l = 0, r = 1;
int ans = 1;
vector<int> ch(256);
ch[s[0]]++;
while (l < n && r <= n) {
while (r <= n && ok(ch)) {
ans = max(ans, r - l);
ch[s[r++]]++;
}
while (l < r && !ok(ch)) {
ch[s[l++]]--;
}
}
return ans;
}
bool ok(vector<int>& ch) {
for (int i = 0; i < 256; i++) {
if (ch[i] > 1) return false;
}
return true;
}
};
(未做)5. Longest Palindromic Substring
https://leetcode.com/problems/longest-palindromic-substring/
最长回文子串。反转和lcs,然后再加一个定位即可。
也可以dp。
2020.03.08(周赛)
(好题)1371. Find the Longest Substring Containing Vowels in Even Counts
位运算,加一个数组表示前k个字符串里的目标字符的个数(奇偶即可),然后对于子串i到j,只需要类似前缀和将j和i-1做差即可。所以题目就转换成对于n+1长度的数组找2个相等且距离最长的距离。
对于这个子问题又有两种解法,如下是一种kn的做法,还可以空间换时间。
class Solution {
public:
int findTheLongestSubstring(string s) {
int n = s.length();
vector<int> a(n+1, 0);
for (int i = 1; i <= n; i++) {
a[i] = a[i-1];
if (s[i-1] == 'a') a[i] ^= 1;
else if (s[i-1] == 'e') a[i] ^= 2;
else if (s[i-1] == 'i') a[i] ^= 4;
else if (s[i-1] == 'o') a[i] ^= 8;
else if (s[i-1] == 'u') a[i] ^= 16;
}
int ans = 0;
for (int i = 0; i < 32; i++) {
vector<int> tmp;
for (int j = 0; j <= n; j++) {
if (a[j] == i) {
tmp.push_back(j);
}
}
if (tmp.size() > 1) ans = max(ans, tmp[tmp.size() - 1] - tmp[0]);
}
return ans;
}
};
将外层的复杂度转换成记录这个字符第一次出现的样子,如果不是第一个出现,就取ans,很巧妙的做法。
class Solution {
public:
int findTheLongestSubstring(string s) {
int n = s.length();
vector<int> a(n+1, 0);
for (int i = 1; i <= n; i++) {
a[i] = a[i-1];
if (s[i-1] == 'a') a[i] ^= 1;
else if (s[i-1] == 'e') a[i] ^= 2;
else if (s[i-1] == 'i') a[i] ^= 4;
else if (s[i-1] == 'o') a[i] ^= 8;
else if (s[i-1] == 'u') a[i] ^= 16;
}
int ans = 0;
vector<int> v(32, -1);
for (int j = 0; j <= n; j++) {
if (v[a[j]] == -1) {
v[a[j]] = j;
} else {
ans = max(ans, j-v[a[j]]);
}
}
return ans;
}
};
1372. Longest ZigZag Path in a Binary Tree
https://leetcode.com/contest/biweekly-contest-21/problems/longest-zigzag-path-in-a-binary-tree/
dfs即可。遍历两遍,一遍是前序过所有节点,二是求长度。每一个结点的左zigzag长度等于他左子节点(若有)的右zigzag长度+1。
但是爆栈了,回过头来看,第二次递归其实没有必要,完全可以用循环做。
Kick Start Round A
https://codingcompetitions.withgoogle.com/kickstart/round/000000000019ffc7/00000000001d3ff3
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<string>
#include<vector>
#include<set>
#include<map>
#include<queue>
#include<deque>
#include<stack>
#define eps 1e-6
#define INF 0x3f3f3f3f
#define sf(a) scanf("%d", &a)
#define sfs(x) scanf("%s", x)
#define sfll(a) scanf("%lld", &a)
#define sf2(a, b) scanf("%d%d", &a, &b)
#define sf3(a, b, c) scanf("%d%d%d", &a, &b, &c)
#define sf4(a, b, c, x) scanf("%d%d%d%d", &a, &b, &c, &x)
#define sfgc(a) scanf("%d", &a);getchar()
#define clr(a, b) memset(a, b, sizeof(a))
typedef long long LL;
using namespace std;
int n, k, ans;
const int MAXN = 2e6+5;
struct Trie{
Trie *next[26];
Trie *father;
char ch;
int cnt;
int depth;
} *root, *tmp;
//
char s[MAXN];
void insert() {
Trie *p = root, *pnew;
for(int i = 0; i < strlen(s); i++){
int x = s[i] - 'A';
if (p->next[x] == NULL){
pnew = new Trie;
pnew->ch = s[i];
pnew->cnt = 1;
pnew->depth = p->depth + 1;
for(int j = 0; j < 26; j++){
pnew->next[j] = NULL;
}
pnew->father = p;
p->next[x] = pnew;
}
else (p->next[x])->cnt++;
p = p->next[x];
}
}
int dfs(Trie* r) {
int tmp = r->cnt;
for (int i = 0; i < 26; i++) {
if (r->next[i] != NULL) {
r->cnt -= dfs(r->next[i]);
}
}
ans += (r->depth) * (r->cnt / k);
return k * (tmp / k);
}
int main()
{
// ios::sync_with_stdio(false);
// freopen("/Users/yeyangulu/Documents/cpp/cpp/input.txt", "r", stdin);
//freopen("output.txt", "w", stdout);
int T;
sf(T);
for (int t = 1; t <= T; t++){
sf2(n, k);
root = new Trie;
root->cnt = 0;
root->depth = 0;
root->father = NULL;
for(int i = 0;i < 26;++ i){
root->next[i] = NULL;
}
ans = 0;
for (int i = 0; i < n; i++) {
sfs(s);
insert();
}
ans = 0;
dfs(root);
cout << "Case #" << t << ": " << ans << endl;
}
return 0;
}