2019字節跳動面試時手撕代碼題


1.  N 階乘末尾0的個數。

輸入描述:

輸入為一行,n(1 ≤ n ≤ 1000)

輸出描述:

輸出一個整數,即題目所求
解法:要判斷末尾有幾個0就是判斷可以整除幾次10。10的因子有5和2,而在0~9之間5的倍數只有一個,2的倍數相對較多,所以本題也就轉換成了求N階乘中有幾個5的倍數。
也就是每多出來一個5,階乘末尾就會多出來一個0,這樣n / 5就能統計完第一層5的個數,依次處理,就能統計出來所有5的個數。同一個思想兩種寫法。
public class Main { public int calcuZero(int n) { int count = 0; for (int i = 1; i <= n; i++) { int cur = i; //如果因數中有一個5那么乘積中就會有一個0,所以計算每一個i中因數5的個數
            while (cur % 5 == 0) { count++; cur /= 5; } } return count; } public static void main(String[] args) { System.out.println(new Main().calcuZero(30)); } }
#include<iostream>
using namespace std; int main() { int n; cin>>n; int count = 0; while(n) { n /= 5;     //算出當前數字中可以匹配5(5和5的倍數)的個數
        count += n; //累加之
 } cout<<count; return 0; }

2.  判斷一顆二叉樹是否為鏡像對稱

解法:判斷一個數是否為鏡像對稱:先判斷根,在判斷左右子樹。如果左右子樹都為空那就是,如果左右子樹不是同時為空那就不是

當左右子樹都存在的時候,判斷他們的值是否相等,如果相等那么久遞歸的對他們的字節點判斷(左邊的左=右邊的右;左邊的右==右邊的左)

/** * Definition for binary tree * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */
class Solution { public:
    bool isSymmetric(TreeNode *root) { if (!root) return true; return Symmetric(root->left, root->right); } bool Symmetric(TreeNode *left, TreeNode *right){ if (!left && !right) return true; if (!left || !right) return false; if (left->val == right->val){ return (Symmetric(left->left, right->right) && Symmetric(right->left, left->right)); } return false; } };

3.  給定數組,從數組中取出n個不復用的數的和為sum

深搜,

void findd(vector<int>&vr,int pos,int sum,int m,int& res){ if(sum==m){ res++; return; } else if(sum>m){ return; }else{ if(pos<vr.size()){ sum+=vr[pos]; findd(vr,pos+1,sum,m,res); sum-=vr[pos]; findd(vr,pos+1,sum,m,res); } } }

DP

int main(){ int n=0; int m=0; while(cin>>n>>m){ vector<int> vr(n); for(int i=0;i<n;++i){ cin>>vr[i]; } sort(vr.begin(),vr.end(),greater<int>());
        vector<vector<long long int>>dp(n,vector<long long int>(m+1,0)); for(int i=0;i<n;++i){ dp[i][0]=1; } for(int i=1;i<=m;i++){ if(vr[0]>m)//過濾
                break; if(vr[0]==i) dp[0][i]=1; else dp[0][i]=0; } for(int i=1;i<n;++i){ if(vr[i]>m)  //過濾
                continue; for(int j=1;j<=m;++j){ if(j-vr[i]>=0) dp[i][j]=dp[i-1][j]+dp[i-1][j-vr[i]]; else dp[i][j]=dp[i-1][j]; } } cout<<dp[n-1][m]<<endl; } return 0; }

4.  給定一個二叉樹和其中一個節點,如何找出中序遍歷順序的下一個節點?樹中的節點除了有兩個分別指向左右子節點的指針以外,還有一個指向父節點的指針.

解法:如果一個節點有右子樹,那么它的下一個節點就是它的右子樹中的最左子節點。

如果沒有右子樹,且它是父節點的左子節點,那么它的下一個節點就是它的父節點。

如果一個節點即沒有右子樹,並且它還是父節點的右子節點,這種情況比較復雜。我們可以沿着指向父節點的指針一直向上遍歷,直到找到一個是它父節點的左子節點的節點。如果這樣的節點存在,那么這個節點的父節點就是我們要找的下一個節點。

如果一個節點不滿足上述所有情況,那么它應該就是中序遍歷的最后一個節點。所以返回NULL

struct BinaryTreeNode { int val; BinaryTreeNode* parent; BinaryTreeNode* left; BinaryTreeNode* right; }; BinaryTreeNode* GetNext(BinaryTreeNode* root) { if (root == NULL) return NULL; BinaryTreeNode* next_node = NULL; //如果節點有右子樹,那么它的下一個節點就是它的右子樹中最左邊的節點
    if (root->right != NULL) { next_node = root->right; while (next_node->left != NULL) next_node = next_node->left; return next_node; } if (root->parent != NULL) { if (root == root->parent->left) {//當前節點是父節點的左子節點
            return root->parent; } else { BinaryTreeNode* parent_node = root->parent; BinaryTreeNode* current_node = root; while (parent_node != NULL && current_node == parent_node->left) { current_node = parent_node; parent_node = parent_node->parent; } return parent_node; } } return NULL; }

5.  求一個無序數組的中位數

求一個無序數組的中位數。 
如:{2,5,4,9,3,6,8,7,1}的中位數為5,{2,5,4,9,3,6,8,7,1,0}的中位數為4和5。

解法:利用快排的思想。任意挑一個元素,以改元素為支點,划分集合為兩部分,如果左側集合長度恰為 (n-1)/2,那么支點恰為中位數。如果左側長度<(n-1)/2, 那么中位點在右側,反之,中位數在左側。 進入相應的一側繼續尋找中位點。

//快排方法,分治思想
int PartSort(int arr[], int left,int right) { int key = arr[right]; while (left < right) { //key右邊,先從左找比key值大
        while (left < right && arr[left] <= key) ++left; if (left < right) { arr[right] = arr[left]; --right; } //從右找比key小
        while (left < right && arr[right] >= key) --right; if (left < right) { arr[left] = arr[right]; ++left; } } arr[left] = key; return left; } void GetMid3(int arr[],int size) { int left = 0; int right = size - 1; int mid = size / 2; int div = PartSort(arr, left, right); while (div != mid) { if (div < mid)//右半區間
            div = PartSort(arr, div + 1, right); else div = PartSort(arr, left, div - 1); } cout << "中位數" << arr[div] << endl; }

6.  有序的數組中找到某一目標值首次出現的下標

給定一個升序的數組,這個數組中可能含有相同的元素,並且給定一個目標值。要求找出目標值在數組中首次出現的下標。 
思想:題目給出有序數組,應該想到利用二分查找來做。找到左鄰居,使其值加一。利用二分查找,算法復雜度為O(logn)

#include<iostream>
using namespace std; int findsearch(int *p, int length, int target) { int left = 0; int right = length-1 ; if (p[right - 1] < target&&length<0&&p==NULL) return - 1; while (left < right) { int mid = (left + right) / 2; if (p[mid] < target) left = mid + 1; else right = mid; } if (p[left] == target) return left; else
        return -1; } int main() { int p[] = { 4,6,6,6,6 }; int length = 5; int target =6; int index = findsearch(p, length, target); cout << index << endl; }

找到有序數組中某一目標值在數組中的開始下標以及終止下標以及目標值出現的次數。也可以用下面的方法:

#include <iostream>
using namespace std; //查找指定數字在有序數組中出現的次數,isLeft標記最左和最右
int FindCntofNum(int a[], int len, int num, bool isLeft) { int left = 0, right = len - 1; int pos, mid; while (left <= right)//二分查找
 { mid = (left + right) / 2; if (a[mid] < num) left = mid + 1; else if (a[mid] > num) right = mid - 1; else { pos = mid; if (isLeft)//查找最左值 right = mid - 1; else//查找最右值 left = mid + 1; } } return pos;//返回最終查找到的位置
} int main() { int a[7] = { 1, 2, 3, 4, 4, 5 ,6}; int left, right, dst; left = FindCntofNum(a, 7, 4, true); right = FindCntofNum(a, 7, 4, false); dst = right - left + 1; cout<< dst<<endl; return 0; }

7.  給兩個鏈表,每個節點存儲一個數字,實現兩個節點之間的數字相加,返回相加后的數字鏈表

/** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode(int x) { val = x; } * } */
public class Solution { public ListNode addTwoNumbers(ListNode l1, ListNode l2) { ListNode l3 = new ListNode(0); ListNode res = l3; int value = 0; int flag = 0; while (l1 != null || l2 != null || flag == 1) { int sum = flag; sum += (l1 != null ? l1.val : 0) + (l2 != null ? l2.val : 0); l1 = (l1 != null ? l1.next : null); l2 = (l2 != null ? l2.next : null); l3.next = new ListNode(sum % 10); flag = sum / 10; l3 = l3.next; } return res.next; } }

8.  全排列

#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm>
using namespace std; typedef long long LL; const int maxn=1000005; int n,m; int a[maxn]; void perm(int s,int e) { if(s==e) { for(int i=0;i<=e;i++) printf("%d ",a[i]); printf("\n"); } else { for(int i=s;i<=e;i++) { swap(a[i],a[s]); perm(s+1,e); swap(a[i],a[s]); } } } int main() { scanf("%d",&n); for(int i=0;i<n;i++) scanf("%d",&a[i]); perm(0,n-1); return 0; }

9.  最大連續和

#include <iostream> #include <cstdio>
using namespace std; int a[9]={-2,1,-3,4,-1,2,1,-5,4}; int l,r; int maxsum(int l,int r) { int ans; if(r==l) return a[l]; int mid=(l+r)/2; ans=max(maxsum(l,mid),maxsum(mid+1,r)); int templ=a[mid],t=0; for(int i=mid;i>=l;i--) templ=max(templ,t+=a[i]); int tempr=a[mid+1];t=0; for(int i=mid+1;i<=r;i++) tempr=max(tempr,t+=a[i]); return max(ans,templ+tempr); } int main() { scanf("%d %d",&l,&r); printf("%d\n",maxsum(l,r)); return 0; }

 

16.  兩數之和

Given an array of integers, return indices of the two numbers such that they add up to a specific target.

You may assume that each input would have exactly one solution, and you may not use the same element twice.

Example:

Given nums = [2, 7, 11, 15], target = 9,

Because nums[0] + nums[1] = 2 + 7 = 9,
return [0, 1].

 解法:用線性的時間復雜度來解決問題,那么就是說只能遍歷一個數字,那么另一個數字呢,我們可以事先將其存儲起來,使用一個HashMap,來建立數字和其坐標位置之間的映射,我們都知道HashMap是常數級的查找效率,這樣,我們在遍歷數組的時候,用target減去遍歷到的數字,就是另一個需要的數字了,直接在HashMap中查找其是否存在即可。

public class Solution { public int[] twoSum(int[] nums, int target) { HashMap<Integer, Integer> m = new HashMap<Integer, Integer>(); int[] res = new int[2]; for (int i = 0; i < nums.length; ++i) { m.put(nums[i], i); } for (int i = 0; i < nums.length; ++i) { int t = target - nums[i]; if (m.containsKey(t) && m.get(t) != i) { res[0] = i; res[1] = m.get(t); break; } } return res; } }

17.  三數之和

給定一個包含 n 個整數的數組 nums,判斷 nums 中是否存在三個元素 a,b,c ,使得 a + b + c = 0 ?找出所有滿足條件且不重復的三元組。

注意:答案中不可以包含重復的三元組。

例如, 給定數組 nums = [-1, 0, 1, 2, -1, -4],

滿足要求的三元組集合為:
[
  [-1, 0, 1],
  [-1, -1, 2]
]
class Solution { public: vector<vector<int>> threeSum(vector<int>& nums) { vector<vector<int>> res; sort(nums.begin(), nums.end()); if (nums.empty() || nums.back() < 0 || nums.front() > 0) return {}; for (int k = 0; k < nums.size(); ++k) { if (nums[k] > 0) break; if (k > 0 && nums[k] == nums[k - 1]) continue; int target = 0 - nums[k]; int i = k + 1, j = nums.size() - 1; while (i < j) { if (nums[i] + nums[j] == target) { res.push_back({nums[k], nums[i], nums[j]}); while (i < j && nums[i] == nums[i + 1]) ++i; while (i < j && nums[j] == nums[j - 1]) --j; ++i; --j; } else if (nums[i] + nums[j] < target) ++i; else --j; } } return res; } };

18.  四數之和

Given an array S of n integers, are there elements a, b, c, and d in S such that a + b + c + d = target? Find all unique quadruplets in the array which gives the sum of target.

Note:

  • Elements in a quadruplet (a,b,c,d) must be in non-descending order. (ie, a ≤ b ≤ c ≤ d)
  • The solution set must not contain duplicate quadruplets.
    For example, given array S = {1 0 -1 0 -2 2}, and target = 0.

    A solution set is:
    (-1,  0, 0, 1)
    (-2, -1, 1, 2)
    (-2,  0, 0, 2)
class Solution { public: vector<vector<int>> fourSum(vector<int> &nums, int target) { set<vector<int>> res; sort(nums.begin(), nums.end()); for (int i = 0; i < int(nums.size() - 3); ++i) { for (int j = i + 1; j < int(nums.size() - 2); ++j) { if (j > i + 1 && nums[j] == nums[j - 1]) continue; int left = j + 1, right = nums.size() - 1; while (left < right) { int sum = nums[i] + nums[j] + nums[left] + nums[right]; if (sum == target) { vector<int> out{nums[i], nums[j], nums[left], nums[right]}; res.insert(out); ++left; --right; } else if (sum < target) ++left; else --right; } } } return vector<vector<int>>(res.begin(), res.end()); } };

19.  最近三數之和

Given an array S of n integers, find three integers in S such that the sum is closest to a given number, target. Return the sum of the three integers. You may assume that each input would have exactly one solution.

    For example, given array S = {-1 2 1 -4}, and target = 1.

    The sum that is closest to the target is 2. (-1 + 2 + 1 = 2).
class Solution { public: int threeSumClosest(vector<int>& nums, int target) { int closest = nums[0] + nums[1] + nums[2]; int diff = abs(closest - target); sort(nums.begin(), nums.end()); for (int i = 0; i < nums.size() - 2; ++i) { int left = i + 1, right = nums.size() - 1; while (left < right) { int sum = nums[i] + nums[left] + nums[right]; int newDiff = abs(sum - target); if (diff > newDiff) { diff = newDiff; closest = sum; } if (sum < target) ++left; else --right; } } return closest; } };

20.  三數之和較小值

Given an array of n integers nums and a target, find the number of index triplets i, j, k with 0 <= i < j < k < n that satisfy the condition nums[i] + nums[j] + nums[k] < target.

For example, given nums = [-2, 0, 1, 3], and target = 2.

Return 2. Because there are two triplets which sums are less than 2:

[-2, 0, 1]
[-2, 0, 3]

Follow up:
Could you solve it in O(n2) runtime?

// O(n^2)
class Solution { public: int threeSumSmaller(vector<int>& nums, int target) { if (nums.size() < 3) return 0; int res = 0, n = nums.size(); sort(nums.begin(), nums.end()); for (int i = 0; i < n - 2; ++i) { int left = i + 1, right = n - 1; while (left < right) { if (nums[i] + nums[left] + nums[right] < target) { res += right - left; ++left; } else { --right; } } } return res; } };

 

38.  x 的平方根

實現 int sqrt(int x) 函數。

計算並返回 x 的平方根,其中 x 是非負整數。

由於返回類型是整數,結果只保留整數的部分,小數部分將被舍去。

示例 1:

輸入: 4
輸出: 2

示例 2:

輸入: 8
輸出: 2
說明: 8 的平方根是 2.82842..., 
     由於返回類型是整數,小數部分將被舍去。

 我們能想到的方法就是算一個候選值的平方,然后和x比較大小,為了縮短查找時間,我們采用二分搜索法來找平方根。

class Solution { public: int mySqrt(int x) { if (x <= 1) return x; int left = 0, right = x; while (left < right) { int mid = left + (right - left) / 2; if (x / mid >= mid) left = mid + 1; else right = mid; } return right - 1; } };

39.  第二高的薪水

編寫一個 SQL 查詢,獲取 Employee 表中第二高的薪水(Salary) 。

+----+--------+
| Id | Salary |
+----+--------+
| 1  | 100    |
| 2  | 200    |
| 3  | 300    |
+----+--------+

例如上述 Employee 表,SQL查詢應該返回 200 作為第二高的薪水。如果不存在第二高的薪水,那么查詢應返回 null

+---------------------+
| SecondHighestSalary |
+---------------------+
| 200                 |
+---------------------+
select max(Salary) as SecondHighestSalary from Employee e1 where (select max(Salary) from Employee e2 where e1.Salary<e2.Salary)

48.  字符串的排列

給定兩個字符串 s1 和 s2,寫一個函數來判斷 s2 是否包含 s1 的排列。

換句話說,第一個字符串的排列之一是第二個字符串的子串。

示例1:

輸入: s1 = "ab" s2 = "eidbaooo"
輸出: True
解釋: s2 包含 s1 的排列之一 ("ba").

示例2:

輸入: s1= "ab" s2 = "eidboaoo"
輸出: False
解法可參考:https://www.cnblogs.com/jkzr/p/10622052.html

 49.  Java實現中文數字轉阿利伯數字

/** * @param chineseNumber * @return */ @SuppressWarnings("unused") private static int chineseNumber2Int(String chineseNumber){ int result = 0; int temp = 1;//存放一個單位的數字如:十萬
        int count = 0;//判斷是否有chArr
        char[] cnArr = new char[]{'','','','','','','','',''}; char[] chArr = new char[]{'','','','',''}; for (int i = 0; i < chineseNumber.length(); i++) { boolean b = true;//判斷是否是chArr
            char c = chineseNumber.charAt(i); for (int j = 0; j < cnArr.length; j++) {//非單位,即數字
                if (c == cnArr[j]) { if(0 != count){//添加下一個單位之前,先把上一個單位值添加到結果中
                        result += temp; temp = 1; count = 0; } // 下標+1,就是對應的值
                    temp = j + 1; b = false; break; } } if(b){//單位{'十','百','千','萬','億'}
                for (int j = 0; j < chArr.length; j++) { if (c == chArr[j]) { switch (j) { case 0: temp *= 10; break; case 1: temp *= 100; break; case 2: temp *= 1000; break; case 3: temp *= 10000; break; case 4: temp *= 100000000; break; default: break; } count++; } } } if (i == chineseNumber.length() - 1) {//遍歷到最后一個字符
                result += temp; } } return result; }

 

數字轉中文

import java.io.Console; import java.util.*; public class FirstExample { static String[] units = { "", "十", "百", "千", "萬", "十萬", "百萬", "千萬", "億", "十億", "百億", "千億", "萬億" }; static char[] numArray = { '零', '一', '二', '三', '四', '五', '六', '七', '八', '九' }; public static void main(String[] args) { int num = 233200040; String numStr = foematInteger(num); System.out.println("num= " + num + ", 轉換結果: " + numStr); } private static String foematInteger(int num) { char[] val = String.valueOf(num).toCharArray(); int len = val.length; System.out.println("----" + len); StringBuilder sb = new StringBuilder(); for (int i = 0; i < len; i++) { String m = val[i] + ""; int n = Integer.valueOf(m); boolean isZero = n == 0; String unit = units[(len - 1) - i]; if (isZero) { if ('0' == val[i - 1]) { //當前val[i]的下一個值val[i-1]為0則不輸出零
                    continue; } else { //只有當當前val[i]的下一個值val[i-1]不為0才輸出零
 sb.append(numArray[n]); } } else { sb.append(numArray[n]); sb.append(unit); } } return sb.toString(); } }

50.  二叉樹中和為某一值的路徑

/* struct TreeNode { int val; struct TreeNode *left; struct TreeNode *right; TreeNode(int x) : val(x), left(NULL), right(NULL) { } };*/
class Solution { public: vector<vector<int>> result; vector<int> elem; void dfs(TreeNode* root, int expectNumber){ elem.push_back(root->val); if(root->val==expectNumber && root->left==NULL && root->right==NULL){//到達了葉子節點且從根節點到葉子節點的和等於整數
 result.push_back(elem); }else{  //否則如果不是葉子節點,繼續dfs
            if(root->left) dfs(root->left, expectNumber-root->val); if(root->right) dfs(root->right, expectNumber-root->val); }//如果是葉子節點,但是從根節點到葉子節點的和不等於expectNumber,則元素退棧,進行另一路徑的判斷
 elem.pop_back(); } vector<vector<int> > FindPath(TreeNode* root,int expectNumber) { if(root) dfs(root, expectNumber); return result; } };

51.  在二叉搜索樹查找第k大的結點

public static int KthSmallest(TreeNode root, int k) { Stack<TreeNode> s = new Stack<TreeNode>(); TreeNode p = root; while (s.Count > 0 || p != null) { if (p != null) { s.Push(p); p = p.Left; } else { p = s.Pop(); --k; if (k == 0) { return p.value; } p = p.Right; } } return -1; }

52.  求數組中區間中最小數*區間所有數和的最大值

public class test { public static int function(int[] arr) { int len = arr.length; int[] sum = new int[len]; int ans = 0; for (int i = 0; i < len; i++) { //右邊界
            sum[i] = arr[i]; for (int j = i+1; j < len; j++) { if (arr[j] >= arr[i]) { sum[i] += arr[j]; } else { break; } } //左邊界
            for (int j = i-1; j >= 0;j--) { if (arr[j] >= arr[i]) { sum[i] += arr[j]; } else { break; } } ans = Math.max(ans,sum[i]*arr[i]); } return ans; } }
import java.util.Scanner; public class MaxRange { public static void main(String[] args) { Scanner in = new Scanner(System.in); int n = in.nextInt(); int arr[] = new int[n]; for (int i = 0; i < n; i++) { arr[i] = in.nextInt(); } in.close(); System.out.println(getMax(arr, 0, n - 1)); } private static int getMax(int[] arr, int start, int end) { if (arr == null || start > end) { return 0; } int n = end - start + 1; int[][] min = new int[n + 1][n + 1]; int[] sum = new int[n + 1]; sum[0] = 0; // sum[i]即從第一個數加到第i個數的和,也就是arr[0]+...+arr[i-1]
        for (int i = start + 1; i <= end + 1; i++) { sum[i - start] = sum[i - start - 1] + arr[i - start - 1]; } int max = -1; for (int k = 0; k <= end - start; k++) // 左右下標的差,k==0時,區間內有1個數
            for (int i = 0; i <= end - start - k; i++) { int j = i + k; if (k == 0) { min[i][j] = arr[i]; } else { if (arr[j] < min[i][j - 1]) { min[i][j] = arr[j]; } else { min[i][j] = min[i][j - 1]; } } max = Math.max(max, min[i][j] * (sum[j + 1] - sum[i])); } return max; } }

53.  矩陣中的最長遞增路徑

class Solution { private int[] row = {-1,1,0,0}; private int[] col = {0,0,-1,1}; public int longestIncreasingPath(int[][] matrix) { if(matrix.length ==0 || matrix[0].length == 0) return 0; boolean[][] visited = new boolean[matrix.length][matrix[0].length]; int[][] len = new int[matrix.length][matrix[0].length]; int max = 0; for(int i=0;i<matrix.length;i++){ for(int j=0;j<matrix[0].length;j++){ max = Math.max(max,find(matrix,visited,len,i,j)); } } return max; } private int find(int[][] matrix,boolean[][] visited,int[][] len,int x,int y){ if(visited[x][y]) return len[x][y]; len[x][y] = 1; for(int i=0;i<4;i++){ int curX = x + row[i]; int curY = y + col[i]; if(curX >=0 && curX < matrix.length && curY >=0 && curY<matrix[0].length && matrix[curX][curY] < matrix[x][y]){ len[x][y] = Math.max(len[x][y],find(matrix,visited,len,curX,curY)+1); } } visited[x][y] = true; return len[x][y]; } }

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM