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