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;

參考代碼:

 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++

 

 

 

 

 

 

發佈了675 篇原創文章 · 獲贊 30 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章