【2020年3月】每月打卡

————————

后记:没想到这么快就拿到了腾讯的暑期实习offer,所以把其他厂的面试全推了,这个打卡也就懒得继续了,直接弃坑…………

————————

 

一直刷hard不是什么好方法,决定改一下刷题的方式,刷下面链接里的常问题。

https://leetcode.com/problemset/top-interview-questions/

目录

2020.03.07

287. Find the Duplicate Number

328. Odd Even Linked List

230. Kth Smallest Element in a BST

1. Two Sum

2. Add Two Numbers

3. Longest Substring Without Repeating Characters

(未做)5. Longest Palindromic Substring

2020.03.08(周赛)

(好题)1371. Find the Longest Substring Containing Vowels in Even Counts

1372. Longest ZigZag Path in a Binary Tree

Kick Start Round A


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

https://leetcode.com/contest/biweekly-contest-21/problems/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;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值