leetcode 字节跳动模拟面试编程题(持续更新~)

模拟一

第一题  字符串中的单词个数(简单)

统计字符串中的单词个数,这里的单词指的是连续的不是空格的字符。

请注意,你可以假定字符串里不包括任何不可打印的字符。

示例:

输入: "Hello, my name is John"
输出: 5
 
 题解:注意开头的空格。然后就一直while判断就行了,看看有多少个被空格间隔的单词。
 
参考代码:
 1 class Solution {
 2 public:
 3     int countSegments(string s) {
 4         int len=s.length();
 5         int ans=0,i=0;
 6         if(len==0) return 0;
 7         while(i<len)
 8         {
 9             while(s[i]==' ' && i<len) ++i;
10             
11             if(s[i]!=' ' && i<len)
12             {
13                 while(s[i]!=' ' && i<len) ++i;
14                 ans++;
15             }
16         }
17         return ans;
18     }
19 };
C++
 

第二题 两数相加 II(中等)

给定两个非空链表来代表两个非负整数。数字最高位位于链表开始位置。它们的每个节点只存储单个数字。将这两数相加会返回一个新的链表。

你可以假设除了数字 0 之外,这两个数字都不会以零开头。

进阶:

如果输入链表不能修改该如何处理?换句话说,你不能对列表中的节点进行翻转。

示例:

输入: (7 -> 2 -> 4 -> 3) + (5 -> 6 -> 4)
输出: 7 -> 8 -> 0 -> 7


题解:

  将两个链表反转之后,按照位置加即可,设置一个进位add;

扫描二维码关注公众号,回复: 9086420 查看本文章

参考代码:

 1 /**
 2  * Definition for singly-linked list.
 3  * struct ListNode {
 4  *     int val;
 5  *     ListNode *next;
 6  *     ListNode(int x) : val(x), next(NULL) {}
 7  * };
 8  */
 9 class Solution {
10 public:
11     ListNode* addTwoNumbers(ListNode *l1, ListNode *l2) {
12         ListNode* tmp = new ListNode(-1), *cur = tmp;
13         int cnt = 0;
14         l1 = reverseList(l1);
15         l2 = reverseList(l2);
16         while (l1 || l2) {
17             int val1 = l1 ? l1 -> val : 0;
18             int val2 = l2 ? l2 -> val : 0;
19             int sum = val1 + val2 + cnt;
20             cnt = sum / 10;
21             cur -> next = new ListNode(sum % 10);
22             cur = cur -> next;
23             if (l1) l1 = l1 -> next;
24             if (l2) l2 = l2 -> next;
25         }
26         if (cnt) cur -> next = new ListNode(1);
27         return reverseList(tmp -> next);
28     }
29 
30     ListNode* reverseList(ListNode *head) {
31         if (!head) return head;
32         ListNode* dummy = new ListNode(-1);
33         dummy -> next = head;
34         ListNode* cur = head;
35         while (cur -> next) {
36             ListNode *tmp = cur -> next;
37             cur -> next = tmp -> next;
38             tmp -> next = dummy -> next;
39             dummy -> next = tmp;
40         }
41         return dummy -> next;
42     }
43 };
C++

第三题 最小区间(困难)

你有 k 个升序排列的整数数组。找到一个最小区间,使得 k 个列表中的每个列表至少有一个数包含在其中。

我们定义如果 b-a < d-c 或者在 b-a == d-c 时 a < c,则区间 [a,b] 比 [c,d] 小。

示例 1:

输入:[[4,10,15,24,26], [0,9,12,20], [5,18,22,30]]
输出: [20,24]
解释: 
列表 1:[4, 10, 15, 24, 26],24 在区间 [20,24] 中。
列表 2:[0, 9, 12, 20],20 在区间 [20,24] 中。
列表 3:[5, 18, 22, 30],22 在区间 [20,24] 中。

注意:

  1. 给定的列表可能包含重复元素,所以在这里升序表示 >= 。
  2. 1 <= k <= 3500
  3. -105 <= 元素的值 <= 105
  4. 对于使用Java的用户,请注意传入类型已修改为List<List<Integer>>。重置代码模板后可以看到这项改动。

题解:

使用优先队列(小顶堆),首先将k个数组的第一个元素加入队列,并记录最大值。然后用最大值-堆顶元素(即最小值)去更新答案。然后把堆顶的元素所在数组的指针向后移,如果已经到达数组末尾则跳出循环,输出答案。

参考代码:

 1 class node {
 2 public:
 3     int row;
 4     int col;
 5     int val;
 6     node(int ir, int ic, int iv) {
 7         row = ir;
 8         col = ic;
 9         val = iv;
10     }
11 };
12 
13 class cmp {
14 public:
15     bool operator() (const node &lhs, const node &rhs) {
16         return lhs.val > rhs.val;
17     }
18 };
19 
20 class Solution {
21 public:
22     vector<int> smallestRange(vector<vector<int>>& nums) {
23         priority_queue<node, vector<node>, cmp> pqn;
24         const int k = nums.size();
25         int max = -INT_MAX;
26         for (int i = 0; i < k; i++) {
27             if (nums[i][0] > max) {
28                 max = nums[i][0];
29             }
30             pqn.push(node(i, 0, nums[i][0]));            
31         }
32         int lret = 0;
33         int rret = INT_MAX;
34         bool has_next = true;
35         do {
36             auto min = pqn.top();
37             pqn.pop();
38             //cout << min.val << "," << max << endl;
39             if (max - min.val < rret - lret) {
40                 lret = min.val;
41                 rret = max;
42             }
43             min.col++;
44             if (min.col >= nums[min.row].size()) {
45                 has_next = false;
46             } else {
47                 min.val = nums[min.row][min.col];
48                 if (max < min.val)
49                     max = min.val;
50                 pqn.push(min);
51             }
52         } while(has_next);
53         return {lret, rret};
54     }
55 };
C++

模拟二

第一题 重复的DNA序列(中等)

所有 DNA 都由一系列缩写为 A,C,G 和 T 的核苷酸组成,例如:“ACGAATTCCG”。在研究 DNA 时,识别 DNA 中的重复序列有时会对研究非常有帮助。

编写一个函数来查找 DNA 分子中所有出现超过一次的 10 个字母长的序列(子串)。

示例:

输入:s = "AAAAACCCCCAAAAACCCCCCAAAAAGGGTTT"
输出:["AAAAACCCCC", "CCCCCAAAAA"]

题解:bitset; 因为只有4个字符,所以可以把字符对应为数字。然后两个bitset,判断是否出现过,和是否插入到答案集合。

参考代码:

 1 class Solution {
 2 public:
 3    int charToBit(char c){
 4         switch (c){
 5             case 'A': return 0;
 6             case 'G': return 1;
 7             case 'C': return 2;
 8             case 'T': return 3;
 9         }
10         return -1;  // never happened
11     }
12 
13     vector<string> findRepeatedDnaSequences(string s) {
14         vector<string> res;
15         if(s.size() < 10) return res;
16         bitset<1<<20> S1;
17         bitset<1<<20> S2; // to avoid dulplication
18         //init
19         int val = 0;
20         for(int i=0;i<10;i++){
21             val = val << 2 | charToBit(s[i]);
22         }
23         S1.set(val);
24         int mask = (1 << 20) - 1;
25         for(int i=10;i<s.size();i++){
26             val = ((val << 2) & mask) | charToBit(s[i]);
27             if(S1[val]) {
28                 if (!S2[val]) {
29                     res.push_back(s.substr(i - 9, 10));
30                     S2.set(val);
31                 }
32             }
33             else{
34                 S1.set(val);
35             }
36         }
37         return res;
38     }
39 };
C++

第二题 分割数组的最大值(困难)

给定一个非负整数数组和一个整数 m,你需要将这个数组分成 个非空的连续子数组。设计一个算法使得这 个子数组各自和的最大值最小。

注意:
数组长度 满足以下条件:

  • 1 ≤ n ≤ 1000
  • 1 ≤ m ≤ min(50, n)

示例:

输入:
nums = [7,2,5,10,8]
m = 2

输出:
18

解释:
一共有四种方法将nums分割为2个子数组。
其中最好的方式是将其分为[7,2,5] 和 [10,8],
因为此时这两个子数组各自的和的最大值为18,在所有情况中最小

题解:动态规划。dp[i][j]:表示前i个数分成j个区间所能得到的最大值的最小值。

转移方程为:dp[i][j]=min(dp[i][j],max(dp[k][j-1],pre[i]-pre[j]));

参考代码:

 1 class Solution {
 2 public:
 3     int splitArray(vector<int>& nums, int m) 
 4     {
 5         int n=nums.size();
 6         unsigned long long dp[n+2][m+2];
 7         memset(dp,127,sizeof(dp));
 8         unsigned long long sum[n+3];
 9         sum[0]=dp[0][0]=0;
10         for(int i=1;i<=n;i++)
11             sum[i]=sum[i-1]+nums[i-1];
12         for(int i=1;i<=n;i++)
13         {
14             for(int j=1;j<=m;j++)
15             {
16                 for(int k=0;k<i;k++)
17                 {
18                     dp[i][j]=min(dp[i][j],max(dp[k][j-1],sum[i]-sum[k]));
19                 }
20             }
21         }
22         return dp[n][m];
23     }
24 };
C++

第三题 树中距离之和(困难)

给定一个无向、连通的树。树中有 N 个标记为 0...N-1 的节点以及 N-1 条边 。

第 i 条边连接节点 edges[i][0] 和 edges[i][1] 。

返回一个表示节点 i 与其他所有节点距离之和的列表 ans

示例 1:

输入: N = 6, edges = [[0,1],[0,2],[2,3],[2,4],[2,5]]
输出: [8,12,6,10,10,10]
解释: 
如下为给定的树的示意图:
  0
 / \
1   2
   /|\
  3 4 5

我们可以计算出 dist(0,1) + dist(0,2) + dist(0,3) + dist(0,4) + dist(0,5) 
也就是 1 + 1 + 2 + 2 + 2 = 8。 因此,answer[0] = 8,以此类

题解:两遍dfs。

第一次dfs出以0节点为根的每个节点到根节点的间距离和每个节点的子节点数量。

第二次dfs,从根开始,它的子节点到所有节点的距离= ans[root] (当前节点的父节点到所有节点的距离) - count[i](当前节点的子节点的数量,包含自己)+ size (所有节点的数量) -count[i];

参考代码:

 1 class Solution {
 2 public:
 3      vector<unordered_set<int>> tree;
 4     vector<int> res, count;
 5 
 6     vector<int> sumOfDistancesInTree(int N, vector<vector<int>>& edges) {
 7         tree.resize(N);
 8         res.assign(N, 0);
 9         count.assign(N, 1);
10         for (auto e : edges) {
11             tree[e[0]].insert(e[1]);
12             tree[e[1]].insert(e[0]);
13         }
14         dfs(0, -1);
15         dfs2(0, -1);
16         return res;
17 
18     }
19 
20     void dfs(int root, int pre) {
21         for (auto i : tree[root]) {
22             if (i == pre) continue;
23             dfs(i, root);
24             count[root] += count[i];
25             res[root] += res[i] + count[i];
26         }
27     }
28 
29     void dfs2(int root, int pre) {
30         for (auto i : tree[root]) {
31             if (i == pre) continue;
32             res[i] = res[root] - count[i] + count.size() - count[i];
33             dfs2(i, root);
34         }
35     }
36 };
C++

猜你喜欢

转载自www.cnblogs.com/csushl/p/12295922.html