字节跳动算法整理(代码片段)

yan1345 yan1345     2022-12-12     746

关键词:

无重复字符的最长子串

输入: "abcabcbb"
输出: 3 
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
class Solution 
public:
    int lengthOfLongestSubstring(string s) 
        int m[256] = 0; //存储每个字符在字符串的位置
        res = 0, left = 0;//结果和左边界
        for(int i=0;i<s.size();i++)
            if(m[s[i]] == 0 || m[s[i]]<left)
                res = max(res, i-left+1);//更新res
            
            else//如果s[i]重复出现且s[i]第一次出现的位置在s[left,i]之间
                left = m[s[i]]; //更新left坐标
            
            m[s[i]] = i+1;
        
        return res;
    
;

最长公共前缀 *

class Solution 
public:
    string longestCommonPrefix(vector<string>& strs) 
        if(strs.size() == 0) 
            return "";
        string s = strs[0];//取出第一个字符串,首字母
        for(int i = 1; i< strs.size(); i++) //从第2个字符串,遍历
            while(strs[i].find(s) != 0) //index ==0 字符串开头
                s = s.substr(0,s.size()-1);
                if(s.empty())
                    return "";
            
        
        return s;
    
;

简化路径

本题思路较为简单,采取入栈的方法。先只考虑"/"之间的字符串:

  • 当遇到不是"."".."时的字符串,则将当前元素入栈;
  • 当遇到".."且栈不为空时,则出栈顶部元素;
  • 其他情况不做处理。

问题的关键在于如何识别一个和多个"/",利用string流的办法,先把"/"替换成空格,之后将string绑定到一个istringstream中,通过类似 cin 的方法提取内容 while(cout >> string)

class Solution 
public:
    string simplifyPath(string path) 
        if(path == "/")
            return "/";
        //将字符串中的‘/‘替换为空格
        for(int i = 0; i < path.size(); i++)
            if(path[i] == ‘/‘)
                path[i] = ‘ ‘;
        
        vector<string> stack;    //声明栈,存放两个‘/‘之间的字符串
        istringstream str(path); //声明并绑定一个输入流
        string buf;              //输入流读入的临时缓存
        while(str >> buf)
            if(buf == ".." && !stack.empty() ) //遇到".."且栈不为空则出栈
                stack.pop_back();
            else if(buf != "." && buf != "..") //不是"."和".."的字符串则入栈
                stack.push_back(buf);
        
        if(stack.empty()) //简化结果为空则返回根目录
            return "/";
        string res;       //存放结果
        for(int i = 0; i < stack.size(); i++)
            res = res + "/" + stack[i];
        
        return res;
    
;

复原IP

class Solution 
public:
    vector<string> res;
    vector<string> restoreIpAddresses(string s) 
        string temp = "";
        dfs(s,temp,0);
        return res;
    
    //参数 s 字符串递归减小,temp 返回值路径,最后一个参数控制word数目
    void dfs(string s,string &temp, int word_number)
    
        if(word_number==4)
        
            //cout << temp << "	";
            if(s.empty()) res.push_back(temp);
        else
            if(word_number > 0) temp += ‘.‘;
            for(int i = 1; i <=3 && i <= s.length();i++)
            
                if(valid(s.substr(0,i)))
                	//注意截取操作函数 s.substr(o,i)从pos0截取i个字符
                    temp += s.substr(0,i);
                    //s变短。试探后
                    dfs(s.substr(i,s.length()-i), temp , word_number+1);
                    //回溯i个字符 注意temp不断变长 所以回溯不是 0~i 而是回溯 length - i
                    temp = temp.substr(0,temp.length()-i);
                
            
            temp.pop_back();
        
    
    bool valid(const string &s)
        if(s.empty()||(s[0]==‘0‘ && s.size()>1)) return false;
        int val = stoi(s);
        if(val >= 0 && val <= 255) return true;
        return false;
    
;

三数之和

? 先排序

? 以数组中每个元素为三个数中的第一个,在其后找到满足条件的剩下2个

– 因为已经排序,为了避免重复,所以相同元素只处理一次(也就是说,如果nums[i] == nums[i - 1],说明以nums[i]为第一个元素的情况已经处理过,那么跳过,继续处理下一个数)

? 为了找出剩余2个满足要求target = 0 - nums[i]的数,使用两个指针l和r,令sum = nums[l] + nums[r]

– 如果sum > target,则将r向左移动至第一个不等的元素处

– 如果sum < target,则将l向右移动至第一个不等的元素处

– 否则,满足要求,添加到结果中,并将l和r都移动至第一个不等的元素处

class Solution 
public:
    vector<vector<int>> threeSum(vector<int>& nums) 
        if(nums.size() < 3) 
            return vector<vector<int>>();
        
        sort(nums.begin(),nums.end());
    
        vector<vector<int>> res;
        for(int i = 0;i < nums.size() - 2;i++)
            if(i == 0 || nums[i] != nums[i - 1])
                int target = 0 - nums[i];
                int l = i + 1,r = nums.size() - 1;
                while(l < r)
                    int sum = nums[l] + nums[r];
                    if(sum < target)
                        while(l < r && nums[l + 1] == nums[l])    l++;
                        l++;
                    
                    else if(sum > target)
                        while(l < r && nums[r - 1] == nums[r])    r--;
                        r--;
                      
                    else
                        vector<int> triplet = nums[i],nums[l],nums[r];
                        res.push_back(triplet);
                        while(l < r && nums[l + 1] == nums[l])    l++;
                        while(l < r && nums[r - 1] == nums[r])    r--;
                        l++;r--;
                    
                
            
        
        
        return res;
    
;

岛屿的最大面积

给定一个包含了一些 01 的非空二维数组 grid

一个 岛屿 是由一些相邻的 1 (代表土地) 构成的组合,这里的「相邻」要求两个 1 必须在水平或者竖直方向上相邻。你可以假设 grid 的四个边缘都被 0(代表水)包围着。

找到给定的二维数组中最大的岛屿面积。(如果没有岛屿,则返回面积为 0 。)

当遇到1时,使用DFS求该岛屿的面积,然后与最大值比较,如果更大则更新最大值。为了防止重复求相同岛屿的面积,在DFS过程中,将1设置为0
class Solution 
public:
    int maxAreaOfIsland(vector<vector<int>>& grid) 
        if(grid.size() == 0)
            return 0;
        
        int res = 0;
        int rows = grid.size(),columns = grid[0].size();   
        for(int i = 0;i < rows;i++)
            for(int j = 0;j < columns;j++)
                if(grid[i][j] == 1)
                    int area = DFS(grid,i,j,rows,columns);
                    res = area > res ? area : res; 
                
            
        
        
        return res;
    
    
    int DFS(vector<vector<int>> &grid,int row,int column,int rows,int columns)
        //越界或者不连通
        if(row < 0 || row >= rows || column < 0 
        || column >= columns || grid[row][column] == 0)
            return 0;
        
        int count = 1;
        grid[row][column] = 0;//防止重复计算
        /*遍历该顶点的四个方向*/
        count += DFS(grid,row - 1,column,rows,columns);
        count += DFS(grid,row + 1,column,rows,columns);
        count += DFS(grid,row,column - 1,rows,columns);
        count += DFS(grid,row,column + 1,rows,columns);
        
        return count;
    
;
 

搜索旋转排序数组

给你一个整数数组 nums ,和一个整数 target

该整数数组原本是按升序排列,但输入时在预先未知的某个点上进行了旋转。(例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] )。

请你在数组中搜索 target ,如果数组中存在这个目标值,则返回它的索引,否则返回 -1

class Solution 
public:
    int search(vector<int>& nums, int target) 
        int l = 0,r = nums.size() - 1;
        while(l <= r)
            int mid = (l + r) / 2;
            if(nums[mid] == target) return mid;
            if(nums[l] < nums[r])
                if(nums[mid] < target)   
                    l = mid + 1;
                else                     
                    r = mid - 1;
            
            else
                if(nums[mid] >= nums[l])//mid在左边
                    if(target > nums[r] && target < nums[mid])  
                        r = mid - 1;
                    else    
                        l = mid + 1;
                
                else//mid在右边
                    if(target > nums[mid] && target < nums[l])  
                        l = mid + 1;
                    else    
                        r = mid - 1;
                
            
        
        return -1;
    
;

朋友圈

班上有 N 名学生。其中有些人是朋友,有些则不是。他们的友谊具有是传递性。如果已知 A 是 B 的朋友,B 是 C 的朋友,那么我们可以认为 A 也是 C 的朋友。所谓的朋友圈,是指所有朋友的集合。

给定一个 N * N 的矩阵 M,表示班级中学生之间的朋友关系。如果M[i][j] = 1,表示已知第 i 个和 j 个学生互为朋友关系,否则为不知道。你必须输出所有学生中的已知的朋友圈总数。

提示:

  • 1 <= N <= 200

  • M[i][i] == 1

  • M[i][j] == M[j][i]

    
    

接雨水

给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。

示例 1:

技术图片

输入:height = [0,1,0,2,1,0,1,3,2,1,2,1]
输出:6
解释:上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)。 

示例 2:

输入:height = [4,2,0,3,2,5]
输出:9

提示:

  • n == height.length

  • 0 <= n <= 3 * 104

  • 0 <= height[i] <= 105

  • 使用两个变量max_left和max_right,分别表示左边柱子的最高者和右边柱子的最高者,初始化为最左边柱子的高度和最右边柱子的最高者
    另外使用两个指针left_bar和right_bar,分别表示左边的一个柱子和右边的一个柱子,初始化为最左边的柱子和最右边的柱子。现在不考虑中间的柱子怎么样,只分析这两个指针所表示的柱子
    假设left_bar和right_bar中高度较低者为left_bar:
    ?如果left_bar比max_left要低,那么left_bar上面能储水max_left-left_bar
    ?否则,left_bar比左边的柱子都要高,那么需要更新max_left的值
    经过上面的处理后,递增left_bar,继续处理下一个柱子
    同理,如果高度较低者为right_bar:
    ?如果right_bar比max_right要低,那么right_bar上面能储水max_right-right_bar
    ?否则,right_bar比右边的柱子都要高,那么需要更新max_right的值
    经过上面的处理后,递减right_bar,继续处理下一个柱子
    这里可能有个疑问:为什么增加储水量时不考虑另外一个边界?原因在于每次更新max_left或max_right时,都是left_bar和right_bar中高度较低者,因此,另外一边必然存在一个边界大于max_left或max_right

class Solution 
public:
   int trap(vector<int>& height) 
       int water = 0,sz = height.size();
       int left_bar = 0,right_bar = sz - 1;
       int max_left = 0,max_right = 0;
       
       while(left_bar < right_bar)
           if(height[left_bar] < height[right_bar])
               if(height[left_bar] < max_left)
                   water += max_left - height[left_bar];
               else    
                   max_left = height[left_bar];
               left_bar++;
           
           else
               if(height[right_bar] < max_right) 
                   water += max_right - height[right_bar];
               else    
                   max_right = height[right_bar];
               right_bar--;
           
       
       
       return water;
   
;
//时间复杂度:O(n)  空间复杂度:O(1)

反转链表

反转一个单链表。

示例:

输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL

进阶:
你可以迭代或递归地反转链表。你能否用两种方法解决这道题?

1)迭代

每次循环将curr.next修改为前一节点

因为需要将当前节点的next节点修改为前一节点,所以需要用一个指针prev记录前一节点。同时,由于修改了当前节点的next节点后,无法访问原来的next节点,因此需要一个指针next,在修改前记录原来的next节点

? 时间复杂度:O(n)

? 空间复杂度:O(1)

class Solution 
public:
    ListNode* reverseList(ListNode* head) 
        ListNode *curr = head,
        *next = head ? head->next : NULL,
        *prev = NULL;
        while(curr)
            curr->next = prev;
            prev = curr;
            curr = next;
            if(next)
                next = next->next;
        
        
        return prev;
    
;

递归

class Solution 
public:
    ListNode* reverseList(ListNode* head) 
        if(head == NULL || head->next == NULL) 
            return head;
        ListNode* p = reverseList(head->next);
        head->next->next = head;
        head->next = NULL;
        return p;
    
   ;

两数相加

给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。

如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。

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

示例:

输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
输出:7 -> 0 -> 8
原因:342 + 465 = 807
//?可以在新链表头结点之前创建一个辅助节点来便利处理
//?要注意链表处理完后可能还有进位,此时还需创建一个节点
class Solution 
public:
    ListNode *addTwoNumbers(ListNode *l1, ListNode *l2) 
        ListNode preHead(0), *p = &preHead;
        int extra = 0;
        while (l1 || l2 || extra) 
            int sum = (l1 ? l1->val : 0) + (l2 ? l2->val : 0) + extra;
            extra = sum / 10;
            p->next = new ListNode(sum % 10);
            p = p->next;
            l1 = l1 ? l1->next : l1;
            l2 = l2 ? l2->next : l2;
        
        return preHead.next;
    
;

合并K个升序链表

给你一个链表数组,每个链表都已经按升序排列。

请你将所有链表合并到一个升序链表中,返回合并后的链表。

示例 1:

输入:lists = [[1,4,5],[1,3,4],[2,6]]
输出:[1,1,2,3,4,4,5,6]
解释:链表数组如下:
[
1->4->5,
1->3->4,
  2->6
  ]
  将它们合并到一个有序链表中得到。
1->1->2->3->4->4->5->6
class Solution 
public:
   ListNode* merge(ListNode* l1, ListNode* l2) 
        if (l1 == NULL) return l2;
        if (l2 == NULL) return l1;
        ListNode* pre = new ListNode(0);
        ListNode* cur = pre;
        while (l1 && l2) 
            if (l1->val <= l2->val) 
                cur->next = l1;
                l1 = l1->next;
             else 
                cur->next = l2;
                l2 = l2->next;
            
            cur = cur->next;
        
        cur->next = l1 != NULL ? l1 : l2;
        return pre->next;
    
    ListNode* mergeKLists(vector<ListNode*>& lists) 
         if (lists.size()== 0) return NULL;
        // 分组间隔每次扩大两倍
        int len = lists.size();
        int interval = 1;
        while (interval < len) 
            // 根据当前间隔,两两合并,合并后的结果保存在两个链表的第一个
            for (int i = 0; i < len - interval; i += 2 * interval) 
                lists[i]  = merge(lists[i], lists[i + interval]);
            
            interval *= 2;
        

        return lists[0];
    
;

买卖股票的最佳时机

给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。

如果你最多只允许完成一笔交易(即买入和卖出一支股票一次),设计一个算法来计算你所能获取的最大利润。

注意:你不能在买入股票前卖出股票。

示例 1:

输入: [7,1,5,3,6,4]
输出: 5
解释: 在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。
     注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格;同时,你不能在买入前卖出股票。

示例 2:

输入: [7,6,4,3,1]
输出: 0
解释: 在这种情况下, 没有交易完成, 所以最大利润为 0。
class Solution 
public:
    int maxProfit(vector<int>& prices) 
        int buy = INT_MAX,sell,maxprofit = 0;
        for(int i = 0;i < prices.size();i++)
            if(prices[i] < buy) 
                buy = prices[i];
            else if(prices[i] > buy) 
                sell = prices[i];       
                if(sell - buy > maxprofit)  maxprofit = sell - buy;
            
        
        return maxprofit;
    
;

买卖股票的最佳时机 II

给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。

设计一个算法来计算你所能获取的最大利润。你可以尽可能地完成更多的交易(多次买卖一支股票)。

注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。

class Solution 
public:
    int maxProfit(vector<int>& prices) 
        if(prices.size() <= 1)  return 0;

        vector<int> dp(3,0);
        vector<int> local(3,0);
        
        for(int i = 1;i < prices.size();i++)
            for(int k = 2;k > 0;k--)
                local[k] = prices[i] - prices[i - 1] + max(dp[k - 1],local[k]);
                dp[k] = max(dp[k],local[k]);
            
        
        return dp[2];
    
;

最大子序和

给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。

示例:

输入: [-2,1,-3,4,-1,2,1,-5,4]
输出: 6
解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。

进阶:

如果你已经实现复杂度为 O(n) 的解法,尝试使用更为精妙的分治法求解。

class Solution 
public:
    int maxSubArray(vector<int>& nums) 
    	int n = nums.size();
        if(n == 0) return 0;
        
        int tempsum = nums[0], maxsum = nums[0];
        for(int i=1;i<n;i++)
        
        	if(tempsum < 0) 	  //tempsum < 0时,代表对之后的结果无增益 
        	   tempsum = nums[i]; //更新tempsum
			else
			   tempsum += nums[i];
			
			
			maxsum = tempsum > maxsum ? tempsum : maxsum;
        
        
        return maxsum;
	
;

最小栈

设计一个支持 pushpoptop 操作,并能在常数时间内检索到最小元素的栈。

  • push(x) —— 将元素 x 推入栈中。

  • pop() —— 删除栈顶的元素。

  • top() —— 获取栈顶元素。

  • getMin() —— 检索栈中的最小元素。

    class Solution 
    public:
        void push(int value) 
            dataStack.push(value);
            if(minStack.empty() || !minStack.empty() && value < minStack.top())
                minStack.push(value);
            
            else
                minStack.push(minStack.top());
        
        void pop() 
            if(dataStack.empty())
                throw new exception();
            dataStack.pop();
            minStack.pop();
        
        int top() 
            if(dataStack.empty())
                throw new exception();
            return dataStack.top();
        
        int min() 
            if(dataStack.empty())
                throw new exception();
            return minStack.top();
        
    private:
        stack<int> dataStack;
        stack<int> minStack;
    ;
    

LRU 缓存机制

运用你所掌握的数据结构,设计和实现一个 LRU (最近最少使用) 缓存机制

实现 LRUCache 类:

  • LRUCache(int capacity) 以正整数作为容量 capacity 初始化 LRU 缓存
  • int get(int key) 如果关键字 key 存在于缓存中,则返回关键字的值,否则返回 -1
  • void put(int key, int value) 如果关键字已经存在,则变更其数据值;如果关键字不存在,则插入该组「关键字-值」。当缓存容量达到上限时,它应该在写入新数据之前删除最久未使用的数据值,从而为新的数据值留出空间。

进阶:你是否可以在 O(1) 时间复杂度内完成这两种操作?

class LRUCache 
public:
    LRUCache(int capacity) : hashtable() , ls() , cap(capacity) , curr(0) 
    
    int get(int key) 
        if(hashtable.find(key) == hashtable.end())  return -1;
        auto itr = hashtable[key];
        if(itr == ls.begin())
            return itr->second;
        else
            ls.push_front(pair<int,int>(itr->first,itr->second));
            auto new_itr = ls.begin();
            hashtable[key] = new_itr;
            ls.erase(itr);
            return ls.front().second;
        
        return 1;
    
    
    void put(int key, int value) 
        if(hashtable.find(key) != hashtable.end())
            ls.erase(hashtable[key]);
            ls.push_front(pair<int,int>(key,value));
            auto new_itr = ls.begin();
            hashtable[key] = new_itr;
            return;
        
        if(curr == cap)
            hashtable.erase(ls.back().first);
            ls.pop_back();
            curr--;
            
        ls.push_front(pair<int,int>(key,value));
        auto new_itr = ls.begin();
        hashtable[key] = new_itr;
        curr++;
    
private:
    unordered_map<int,list<pair<int,int>>::iterator> hashtable;
    list<pair<int,int>> ls;
    int cap;
    int curr;
;

x 的平方根

实现 int sqrt(int x) 函数。

计算并返回 x 的平方根,其中 x 是非负整数。

由于返回类型是整数,结果只保留整数的部分,小数部分将被舍去。

#include<iostream>
using namespace std;
int main()

        double eps = 1e-6;
        double k = 0.8;  // 输入正数
        double l = 0.0,r,mid;
        if (k>=1) r = k;  // 若输入正数大于1,则右端点设为 k
        if (k<1)  r = 1;  // 若输入整数小于1,则右端点设为 1

    while (fabs(l-k/l)>eps)
    
        mid = l + (r - l) /2 ;   
        if (mid<k/mid)
        
            l = mid;
        
        else 
            r = mid;
        
    
    cout << l << endl;
    return 0;

UTF-8 编码验证

UTF-8 中的一个字符可能的长度为 1 到 4 字节,遵循以下的规则:

  1. 对于 1 字节的字符,字节的第一位设为0,后面7位为这个符号的unicode码。
  2. 对于 n 字节的字符 (n > 1),第一个字节的前 n 位都设为1,第 n+1 位设为0,后面字节的前两位一律设为10。剩下的没有提及的二进制位,全部为这个符号的unicode码。

这是 UTF-8 编码的工作方式:

   Char. number range  |        UTF-8 octet sequence
      (hexadecimal)    |              (binary)
   --------------------+---------------------------------------------
   0000 0000-0000 007F | 0xxxxxxx
   0000 0080-0000 07FF | 110xxxxx 10xxxxxx
   0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx
   0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

给定一个表示数据的整数数组,返回它是否为有效的 utf-8 编码。

注意:
输入是整数数组。只有每个整数的最低 8 个有效位用来存储数据。这意味着每个整数只表示 1 字节的数据。

class Solution 
public:
    bool validUtf8(vector<int>& data) 
        int size = data.size();
        for(int i = 0; i < size; i++)
        
           int bitCount = 0;
           for(int j = 7; j > 0; j--)
           
               if(((data[i] >> j) % 2) == 0)
                   break;
               bitCount ++;
           
           if(bitCount == 1 || bitCount > 4)
               return false;
           if(bitCount + i > size)
               return false;
           for(int j = 0; j < bitCount - 1; j++)
               if(((data[i + j + 1] >> 7) % 2) == 0 
                  || ((data[i + j + 1] >> 6) % 2) != 0)
                   return false;
           if(bitCount != 0)
               i += bitCount - 1;
        
        return true;
    
;

第二高的薪水

编写一个 SQL 查询,获取 Employee 表中第二高的薪水(Salary) 。

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

例如上述 Employee 表,SQL查询应该返回 200 作为第二高的薪水。如果不存在第二高的薪水,那么查询应返回 null

+---------------------+
| SecondHighestSalary |
+---------------------+
| 200                 |
+---------------------+
SELECT (SELECT DISTINCT salary FROM employee ORDER BY salary DESC LIMIT 1 OFFSET 1) AS secondHighestSalary

strcmp

//字符串比较
int strcmp(const char *str1,const char *str2)

    assert(str1 && str2);
    //在判断是否相等时不一定要转换为unsigned char
    while((*str1 == *str2) && *str1)
        str1++;
        str2++;
    
    if(*str1 == *str2)//说明上面循环退出时*str等于0
        return 0;
    //128种扩展ascii码使用最高位来标识,
    //所以在判断返回大于0还是小于0是,要转换为unsigned char,否则结果相反
    return *(unsigned char*)str1 > *(unsigned char*)str2 ? 1 : -1;

strcat

//字符串拼接
char* strcat(char *strDest,const char *strSrc)

    assert(strDest && strSrc);
    char *p = strDest;
    while(*p) 
        p++;
    while(*p++ = *strSrc++);
    return strDest;

strlen

//字符串长度计算
int strlen(const char *str)

    assert(str);
    int len = 0;
    while(*str++)   
        len++;
    return  len;

//字符串长度计算
int strlen(const char *str)

    assert(str);
    return (*str == 0) ? 0 : 1 + strlen(str + 1);  

memcpy

void* memcpy(void *dst,const void *src,size_t size)

    if(dst == NULL || src == NULL)
        return NULL;
    
    char *pdst = (char*)dst;
    char *psrc = (char*)src;
    //有重叠,从高地址开始复制
    if(pdst > psrc && pdst < psrc + size)
        pdst = pdst + size - 1;
        psrc = psrc + size - 1;
        while(size--)
            *pdst-- == *psrc--;
        
    
    //没有重叠,从低地址开始复制
    else
        while(size--)
            *pdst++ = *psrc++;
        
    
    return dst;

strcpy

//字符串拷贝
char* strcpy(char *strDest,const char *strSrc)

    assert(strDest && strSrc);

    char *p = strDest;
    while(*p++ = *strSrc++);
    return strDest;













面试字节跳动后,整理了这20道面试题....(代码片段)

目录1、软件测试流程介绍2、SQL硬删除、软删除3、SQL创建表的方法4、SQL增删改查语法5、索引有哪些,索引的优缺点6、索引的原理7、商品价格9.9,购买2件,提交订单,付款19.78,是什么原因8、微信发红包设计... 查看详情

字节跳动开源最新gan压缩算法,算力消耗可减少至1/46(代码片段)

字节跳动近期开源了一项代号为OMGD的压缩技术。这是字节自研的GAN(生成对抗网络)压缩算法,在保证生成效果不变的前提下,算力消耗最低可以减少到原来的1/46,相比之前业界的最佳压缩效果提升一倍多。... 查看详情

字节跳动2-1算法二轮面试202203-29(代码片段)

罗马数字包含以下七种字符: I, V, X, L,C,D 和 MI      1V      5X      10L      50C      100D      500M      1000这道题对应的是leetcode 中的12.整数转罗马数字packageexample;publicclass... 查看详情

字节跳动抖音电商2-2算法20220331(代码片段)

题目:////n==nums.length//1<=n<=104//0<=nums[i]<=n//nums中的所有数字都独一无二//给定一个包含[0,n]中n个数的数组nums,找出[0,n]这个范围内没有出现在数组中的那个数。//输入:nums=[3,0,1]//输出 查看详情

字节跳动一面(凉)(代码片段)

视频面试,上来就是一道算法题,LeetCode上的原题,440题(qaq,后悔当初没写到) publicintfindKthNumber(intn,intk)intcur=1;--k;while(k>0)longstep=0,first=cur,last=cur+1;while(first<=n)step+=Math.min(n+1,last)-first;first* 查看详情

卧槽!字节跳动《算法中文手册》火了,完整版pdf开放下载!(代码片段)

今天给大家推荐两份来自字节跳动大佬的算法进阶指南,据说有不少小伙伴靠这份指南成功掌握了算法的核心技能,拿到了BAToffer。希望对大家有帮助。第一份资料是70KStar的《labuladong的算法小抄》(作者labuladong)... 查看详情

2021届字节跳动客户端提前批一面凉经(代码片段)

不得不说字节还是很难进的,提前批算是去试了一个水,自己的算法功底,还远远达不到要求,对操作系统,java虚拟机,多线程,进程等知识还有很大的欠缺,深度还远远不够,所以还是努力的刷题吧,希望秋招能顺利进入字... 查看详情

字节跳动2-1三轮大数据方向算法20220330(代码片段)

新鲜出炉,大数据的总监,一上来什么都没问,让我写一个非递归后续遍历。很不好意思让他打脸了,这个题我做过5片了,理解上还是很深刻的。我就想对他说为啥面试连自我介绍都不给我,就让我做题&#... 查看详情

最短时间搞定算法:字节跳动android岗算法题考前突击宝典(代码片段)

前言一个人,一支笔,一个晚上,一个奇迹。这是学生党的常规操作。大学里也同样有很多奇迹的创造者:每次一到期末考试的前几个晚上,各个变身“最强大脑”,上知天文,下晓地理,还精通... 查看详情

字节跳动2018校招算法方向(第一批)——1-最外层点(代码片段)

时间限制:C/C++1秒,其他语言2秒空间限制:C/C++32M,其他语言64MP为给定的二维平面整数点集。定义P中某点x,如果x满足P中任意点都不在x的右上方区域内(横纵坐标都大于x),则称其为... 查看详情

字节跳动2018校招算法方向(第一批)——2-最大值区间(代码片段)

时间限制:C/C++3秒,其他语言6秒空间限制:C/C++128M,其他语言256M给定一个数组序列,需要求选出一个区间,使得该区间是所有区间中经过如下计算的值最大的一个:区间中的最小数*区间所有数的和... 查看详情

去了字节跳动,回来聊一聊字节跳动的面试...(代码片段)

一、算法题一面:1.lc里最长上升子序列的变形题2.实现输入英文单词联想的功能二面:1.矩阵旋转,要求空间复杂度O(1)2.无序的数组的中位数。要求时间复杂度尽可能的小二、计算机网络tcp怎么保证数据包有序主机每... 查看详情

sql查询语句先执行select,字节跳动算法工程师面试(代码片段)

SELECT<返回数据列表>#返回的单列必须在groupby子句中,聚合函数除外DISTINCT#数据除重ORDERBY<排序条件>#排序LIMIT<行数限制>其实,引擎在执行上述每一步时,都会在内存中形成一张虚拟表,然后对虚拟表... 查看详情

字节跳动内部流出python学习路线,大佬整理,堪称python学习路线中的天花板,赶紧收藏(代码片段)

什么是Python?在说Python之前,大家需要先了解一个概念:编程语言。可以理解为计算机语言,在人类的沟通中需要用到汉语、英语等,而要与计算机交流则需要使用编程语言,而Python就是编程语言中的一员... 查看详情

进字节了!(代码片段)

终于进字节跳动了!这里说的不是我自己,而是我的一位朋友。为了成功进入字节,他都做了哪些准备的呢?他准备的重点内容是数据结构和算法。在此,他给大家推荐两份来自字节跳动大佬的算法进阶指南&#... 查看详情

字节跳动2-1算法二轮面试202203-29(代码片段)

罗马数字包含以下七种字符: I, V, X, L,C,D 和 MI      1V      5X      10L      50C      100D      500M      1000这道题对应的是leetcode 中的12.整数转罗马数字packageexample;publicclass... 查看详情

字节跳动八进八出,offer到手,发现项目不重要算法才最重要(代码片段)

...#xff0c;本人刚刚大三结束,去年十二月的时候是投递了字节的视频架构的实习,共三轮技术面+一轮hr面,成功拿到offer实习了五个月。今年秋招提前批是投了抖音架构,共三轮技术面+一轮hr面,已经成功拿... 查看详情

golang开发面经字节跳动(三轮技术面)(代码片段)

文章目录写在前面笔试一面epoll、select、poll区别epoll的水平触发和边缘触发的区别TCP的流量控制为什么有了流量控制还要有拥塞控制?TCP不是可靠传输吗?为什么会丢包呢?那你介绍一下拥塞控制的算法?进程、线程的... 查看详情