zoukankan      html  css  js  c++  java
  • leetcode 牛客编程 子序列 树 数组(积累)

    牛客和leetcode有很多重复
    语言时而c++ 时而go

    子序列问题

    最长递增子序列II

    输出arr的最长递增子序列,如果多个,输出字典序最小的。

    • 二分+dp
      二分找到对应位置,maxLen记录当前位置i结尾的最长子序列值
      后续找最小字典序,从后向前寻找即可。
     vector<int> LIS(vector<int>& arr) {
            // write code here
            if(arr.size()<1) return {};
            vector<int>res; //保留临时结果,单非最终结果
            vector<int>maxLen;  //存放以i处数字结尾的最长子序列长度
            res.push_back(arr[0]);
            maxLen.push_back(1);
            for (int i=1;i<arr.size();i++)
            {
                if(arr[i]>res.back())//大于则放入res即可
                {
                    res.push_back(arr[i]);
                    maxLen.push_back(res.size()); //i处长度增加
                }else{
                    //找到大于等于val的元素位置放入
                    //不手写二分可使用  int pos = lower_bound(res.begin(),res.end(),arr[i])-res.begin();
                   int pos = binary(res,0,res.size()-1,arr[i]);
                    res[pos] = arr[i];
                    maxLen.push_back(pos+1); //坐标+1为长度
                }
            }
            
            //字典序最小的  
            for(int i=arr.size()-1,j = res.size();j>0;i--)
            {
                if(maxLen[i]==j)//长度为j res位置坐标为j-1
                {
                    res[--j] = arr[i];
                }
            }
            return res;
        }
        
        //二分寻找大于等于target位置
        int binary(vector<int> res,int low,int high,int target)
        {
            int mid;
            while(low<=high)
            {
                mid = low+(high-low)/2;
                if(res[mid]>=target)
                {
                    if(mid==0||res[mid-1]<target)
                    {
                          return mid;
                    }
                    else{
                        high = mid-1;
                    }
                }else{
                    low = mid+1;
                }
            }
            return low;
        }
        
    
    最长递增子序列I

    求最长递增子序列长度
    上面会了,此题秒解,返回res长度即可 ,maxLen不需要

    • 二分
    int lengthOfLIS(vector<int>& arr) {
         if(arr.size()<1) return {};
            vector<int>res; //保留临时结果,单非最终结果
            res.push_back(arr[0]);
            for (int i=1;i<arr.size();i++)
            {
                if(arr[i]>res.back())//大于则放入res即可
                {
                    res.push_back(arr[i]);
                }else{
                    //找到大于等于val的元素位置放入
                    //不手写二分可使用  int pos = lower_bound(res.begin(),res.end(),arr[i])-res.begin();
                   int pos = binary(res,0,res.size()-1,arr[i]);
                    res[pos] = arr[i];
                }
            }
            
           return res.size();
        }
        
        //二分寻找大于等于target位置
        int binary(vector<int> res,int low,int high,int target)
        {
            int mid;
            while(low<=high)
            {
                mid = low+(high-low)/2;
                if(res[mid]>=target)
                {
                    if(mid==0||res[mid-1]<target)
                    {
                          return mid;
                    }
                    else{
                        high = mid-1;
                    }
                }else{
                    low = mid+1;
                }
            }
            return low;
        }
    
    
    最长递增子序列个数

    leetcode673
    求最长递增子序列个数

    • 双循环 时间O(n^2)
      dp 为i位置结尾最大子序列(LIS)长度
      count 为i位置最大子序列组合数
     int findNumberOfLIS(vector<int>& nums) {
            int n = nums.size();
            if(n<=0) return 0;
            vector<int>dp(n,1); //i位置结尾的最大子序列
            vector<int>count(n,1);  //i结尾最大子序列的组合个数
            for(int i=1;i<n;i++)
                for (int j = 0;j<i;j++)
                {
                    if(nums[i]>nums[j])
                    {
                        if(dp[j]+1>dp[i])//第一次遍历到
                        {
                            dp[i] = dp[j]+1;
                            count[i] = count[j];
                        }
                        else if(dp[j]+1==dp[i])//第二次遍历
                        {
                            count[i]+=count[j];
                        }
                    }
                }
            int tmp = 0;
            int res = 0;
            for(int i=0;i<n;i++)
            {
                tmp = max(tmp,dp[i]);
            }
            for(int i=0;i<n;i++)
            {
                if(tmp==dp[i])
                    res+=count[i];
            }
            return res;
        }
    
    数组最长连续子序列

    无序数组反最长连续子序列长度
    [100,4,200,1,3,2] 返回4

    • 排序计算
      复杂度应该是排序的O(nlogn)
      排序,后比前面大1,count++,全局记录最大值
    int MLS(vector<int>& arr) {
            // write code here
            if(arr.empty()) return 0;
            int res =0;
            int count=1;
            //sort即可
            FastThree(arr,0,arr.size()-1);
            //sort(arr.begin(),arr.end());
            for(int i=0;i<arr.size()-1;i++)
            {
                if(arr[i+1]-arr[i]==1)
                    count++;
                else if(arr[i+1]==arr[i])
                    continue;
                else
                    count=1;
                res = max(res,count);
            }
            return res;
        }
        //快排写着玩的
        void Fast(vector<int>&arr,int low,int high){
          
            if(low>high)return ;
            int start = low;
            int end = high;
            int tmp = arr[low];
            while(start<end)
            {
                while(start<end&&arr[end]>=tmp) end--;
                arr[start] = arr[end];
                while(start<end&&arr[start]<=tmp) start++;
                arr[end] = arr[start];
            }
            arr[start] = tmp;
            Fast(arr, low, start-1);
            Fast(arr,start+1,high);
        }
        
        //三路快排熟悉一下,因为有重复元素 注意边界值
        void  FastThree(vector<int>&arr,int low ,int high)
        {
            if(low>=high)return ;
            int tmp = arr[low];
            int i=low;
            int j=low;
            int k = high;
            while(i<=k)
            {
                if (arr[i]<tmp) swap(arr[i++], arr[j++]);
                else if(arr[i]>tmp) swap(arr[i],arr[k--]);
                else i++;
            }
            FastThree(arr,low,j);
            FastThree(arr,k+1,high);
        }
    
    • set去重排序
      时空O(n)
    
     int MLS(vector<int>& arr) {
            if(arr.empty())return 0;
            int res =0;
            set<int>hash;
            for(int i=0;i<arr.size();i++)
                hash.insert(arr[i]);
            set<int>::iterator it;
            int num = 0;
            
            for(it = hash.begin();it!=hash.end();it++)
            {
                //包含比当前小1,则计算过,跳过
                if(hash.count(*it-1))continue;
                
                int end = *it; //记录值
                while(hash.count(end+1)) //有比当前+1的,一直找到最后
                    end++;
                
                res = max(res,end-*it+1);//保留最大值
                
            }
            return res;
        }
    
    • 并查集
      待完善

    树相关

    恢复二叉搜索树
    • 法一

    中序遍历保留每个节点,排序后重新赋值 空间O(n)

    var res []int
    var list [] *TreeNode
    func recoverTree(root *TreeNode)  {
    	//记得初始化
    		res = make([]int,0)
    		list = make([]*TreeNode,0)
    		dfs(root)
    		sort.Ints(res)
    		for i:=0;i<len(res);i++{
    			list[i].Val = res[i]
    		}
    }
    
    //中序遍历
    func dfs (root *TreeNode) {
    	if root==nil{
    		return
    	}
    	dfs(root.Left)
    	res = append(res,root.Val)
    	list = append(list,root)
    	dfs(root.Right)
    }
    
    
    • 法二 不用全部排序,找到前面和后面的交换位置 空间仍然是O(N)
    
    
    • 法三
      Morris遍历 空间O(1)
    
    
    判断二叉搜索树,平衡树
    • 二叉搜索树
      中序为顺序,小于上一个不符合
     //c++
     long pre  = LONG_MIN;
        bool isValidBST(TreeNode* root) {
            if(root==NULL)
            return true;
            if(!isValidBST(root->left))//左子数非真
            return false;
            if(root->val<=pre)//中序,当前要大于等于之前
             return false;
            pre =root->val;//记录上一个
            return isValidBST(root->right);
    
        }
    
    • 平衡树
    bool flag = true;
        bool IsBalanced_Solution(TreeNode* pRoot) {
             dfs(pRoot);
            return flag;
            
        }
        int dfs(TreeNode*root)
        {
            if(!root)
                return 0;
            int left = dfs(root->left);
            int right = dfs(root->right);
            
            if(abs(left-right)>1)
            {
                flag = false;
            }
            return right>left?right+1:left+1;
        }
    
    判断镜像
       bool isSymmetric(TreeNode* root) {
            if(root==NULL)
                return true;
            return equal(root->left, root->right);
        }
        
        bool equal(TreeNode*left,TreeNode*right)
        {
            if(left==NULL&&right==NULL)
                return true;
            if(left==NULL||right==NULL)
                return false;
            if(left->val!=right->val)
                return false;
                //左子树右==右子树左,左子树左==右子树右
            return equal(left->left,right->right)&&equal(left->right,right->left);
        }
    
    序列化二叉树

    每个value以!结尾,空用#表示
    牛客和leetcode有略微不同,牛客是char*需要和string进行转换方便写题

     char* Serialize(TreeNode *root) {  
            string res;
            queue<TreeNode*>que; //队列放置
            que.push(root);
            while(!que.empty())
            {
                TreeNode*tmp = que.front();
                que.pop();
                if(tmp==NULL) //NULL跳过
                {
                    res.push_back('#');
                    res.push_back('!');
                    continue;
                }
                res+=to_string(tmp->val);
                res.push_back('!');
                que.push(tmp->left);
                que.push(tmp->right);
            }
            res.pop_back();//去除最后一个!
            char *str = new char[res.length()+1]; //长度+1
            strcpy(str, res.c_str());
            return str;
        }
        
        TreeNode* Deserialize(char *str) {
             if(str==NULL)return NULL;
             string ret(str);
            if(ret.size()==0||ret[0]=='#')
                return NULL;
            
            vector<TreeNode*>res;
            int i=0;
            while(i<ret.size())
            {
               string tmp = "";
               //!为分割
                while(i<ret.size()&&ret[i]!='!')
                {
                    tmp.push_back(ret[i]);
                    i++;
                }
                if(tmp=="#")
                {
                     TreeNode*node = NULL;
                     res.push_back(node);   
                }
                else{
                    TreeNode*node = new TreeNode(NULL);
                    node->val = stoi(tmp);
                    res.push_back(node);
                }
                i++;
            }
            //转换为二叉树形式 
            int j = 1;
            for(int i=0;j<res.size();i++)
            {
                if(!res[i])
                    continue;
                if(i<res.size())
                {
                    res[i]->left = res[j];
                    j++;
                }
                if(i<res.size())
                {
                    res[i]->right =res[j];
                    j++;
                }
            }
            return res[0];
        }
    
    前中,中后构建二叉树

    重点是对于边界值的判断

    • 已知前序中序
    func buildTree(preorder []int, inorder []int) *TreeNode {
    	n:=len(preorder)
    	if n==0{
    		return nil
    	}
    	return dfs(preorder,inorder,0,n-1,0,n-1)
    }
    
    func dfs(preorder []int, inorder []int,preleft,preright ,inoleft,inoright int)*TreeNode{
    	if preleft>preright||inoleft>inoright{
    		return nil
    	}
    	pos:= 0 //中序位置
    	for i:=inoleft;i<=inoright;i++{
    		if inorder[i]==preorder[preleft]{
    			pos = i
    			break
    		}
    	}
    	//左边长度
    	length:=pos-inoleft
    	root:=new(TreeNode)
    	root.Val = preorder[preleft]
    	root.Left = dfs(preorder,inorder,preleft+1,preleft+length,inoleft,pos-1)
    	root.Right = dfs(preorder,inorder,preleft+1+length,preright,pos+1,inoright)
    	return root
    }
    
    • 已知中序后续
    func buildTree(inorder []int, postorder []int) *TreeNode {
    	n:=len(inorder)
    	if n==0{
    		return nil
    	}
    	return dfs(inorder,postorder,0,n-1,0,n-1)
    }
    
    func dfs(inorder []int,postorder []int,inst,inen,post,poen int) *TreeNode {
    	if inst>inen||post>poen{
    		return nil
    	}
    	root:=new(TreeNode)
    	root.Val = postorder[poen]
    
    	//寻找中序位置
    	pos:=0
    	for i:=inst;i<=inen;i++{
    		if inorder[i]==postorder[poen]{
    			pos = i
    			break
    		}
    	}
    	//右半部分长度
    	length:=inen-pos
    	root.Left = dfs(inorder,postorder,inst,pos-1,post,poen-length-1)
    	root.Right = dfs(inorder,postorder,pos+1,inen,poen-length,poen-1)
    	return root
    }
    
    前中后序非递归遍历

    开始不要放入

    • 前序
    func preorderTraversal(root *TreeNode) []int {
    	var res []int
    	rt:=root
    	var stack []*TreeNode
    	//开始不装入
    	for len(stack)!=0||rt!=nil{
    		for rt!=nil{
    			res = append(res,rt.Val)
    			stack = append(stack,rt)
    			rt = rt.Left
    		}
    
    		if len(stack)!=0{
    			tmp:=stack[len(stack)-1]
    			stack = stack[:len(stack)-1]
    			rt = tmp.Right
    		}
    	}
    	return res
    }
    
    • 中序
      和前序类似,在下面装入
    func inorderTraversal(root *TreeNode) []int {
    	res:=make([]int,0)
    	stack:=make([]*TreeNode,0)
    	rt:=root
    	for len(stack)!=0||rt!=nil{
    		for rt!=nil{
    			stack = append(stack,rt)
    			rt = rt.Left
    		}
    
    		tmp:=stack[len(stack)-1]
    		stack = stack[:len(stack)-1]
    		//记录数据放在这里
    		res = append(res,tmp.Val)
    		rt = tmp.Right
    	}
    	return res
    }
    
    • 后序
      map记录是否访问,或者判断右子树是否访问过
    func postorderTraversal(root *TreeNode) []int {
    	res := make([]int,0)
    	//记录访问过的节点
    	hash:=make(map[*TreeNode]bool)
    	stack:=make([]*TreeNode,0)
    	rt:=root
    	for len(stack)!=0||rt!=nil{
    		for rt!=nil{
    			stack = append(stack,rt)
    			rt = rt.Left
    		}
    		//取出栈顶元素
    		tmp:=stack[len(stack)-1]
    		if tmp!=nil&&hash[tmp]{
    			//用过则加入结果,去除栈顶元素
    			stack = stack[:len(stack)-1]
    			res = append(res,tmp.Val)
    		}else{
    			//没用过,记录下,向右
    			hash[tmp] = true
    			rt = tmp.Right
    		}
    	}
    	return res
    }
    
    之字型遍历二叉树
    • 递归,巧妙,每一层一个数组保存数据
    var res [][]int //全局变量
    func zigzagLevelOrder(root *TreeNode) [][]int {
        //dfs
        res = make([][]int,0)
        if root==nil{
            return res
        }
        dfs(root,0)
        return res
    }
    func dfs(root *TreeNode,deepth int){
         if root==nil{
             return 
         }
         if deepth>=len(res){ //进入1层,增加相应的[]int
             res  = append(res,[]int{})
         }
         //0开始偶数鞥正常顺序
         if deepth&1==0{
             res[deepth] = append(res[deepth],root.Val)
         }
         if deepth&1==1{ //奇数层逆序
             res[deepth] = append([]int{root.Val},res[deepth]...)
         }
         dfs(root.Left,deepth+1)
         dfs(root.Right,deepth+1)
    }
    
    
    • 迭代,两个队列,第二次从右向左
    func zigzagLevelOrder(root *TreeNode) [][]int {
        //双队列
        if root==nil{
            return [][]int{}
        }
        res:=make([][]int,0)
        stack1:=make([]*TreeNode,0)
        stack2:=make([]*TreeNode,0)
        stack1 = append(stack1,root)
        for len(stack1)!=0||len(stack2)!=0{
            ret:=make([]int,0)
            size:=len(stack1)
            for i:=0;i<size;i++{
                tmp :=stack1[0]
                stack1 = stack1[1:]
                ret = append(ret,tmp.Val)
                if tmp.Left!=nil{
                    stack2 = append(stack2,tmp.Left)
                }
                if tmp.Right!=nil{
                    stack2 = append(stack2,tmp.Right)
                }
            }
            if len(ret)!=0{
                res =  append(res,ret)
            }
           
            //右向左
            size = len(stack2)
            ret = make([]int,0)
            for i:=size-1;i>=0;i--{
                tmp:=stack2[len(stack2)-1]
                stack2 = stack2[:len(stack2)-1]
                ret = append(ret,tmp.Val)
                if tmp.Right!=nil{
                    stack1 = append([]*TreeNode{tmp.Right},stack1...)
                }
                if tmp.Left!=nil{
                    stack1 = append([]*TreeNode{tmp.Left},stack1...)
                }
            }
             if len(ret)!=0{
                res =  append(res,ret)
            }
        }
        return res
    }
    
    N叉树层序遍历

    bfs放入队列,每次队列长度循环,每个节点的子节点都放入队列

    func levelOrder(root *Node) [][]int {
    	var res [][]int
    	if root==nil{
    		return res
    	}
    	que:=make([]*Node,0)
    	que = append(que,root)
    	for len(que)!=0{
    		lenght:=len(que)
    		tmp:=make([]int,0)
    		for i:=0;i<lenght;i++{
                //每次取第一个,因为下面已经去除第一个
    			tmp = append(tmp,que[0].Val)
                node:=que[0]
    			que = que[1:]
    			for j:=0;j<len(node.Children);j++{
    				if node.Children[j]!=nil{
    					que = append(que,node.Children[j])
    				}
    			}
    		}
    		res = append(res,tmp)
    	}
    	return res
    
    }
    

    数组相关(滑动窗口,二分)

    lt56 合并区间

    二维数组合并区间,先排序再合并

    func merge(intervals [][]int) [][]int {
    	//排序合并
    	if len(intervals)<=1{
    		return intervals
    	}
    	fast(intervals,0,len(intervals)-1) //手撕快排
    	var res [][]int
    	//前一个尾部大于后一个头,则合并,合并的尾为两个尾部最大    [1,3],[2,6】  是[1,6]
    	for i:=0;i<len(intervals);i++{
    		if len(res)==0||intervals[i][0]>res[len(res)-1][1]{
    			res = append(res,intervals[i])
    		}else{
    			res[len(res)-1][1] = max(res[len(res)-1][1],intervals[i][1])
    		}
    	}
    	return res
    }
    
    func max(x,y int)int  {
    	if x>y{
    		return x
    	}else{
    		return y
    	}
    }
    
    func fast(arr [][]int,low,high int)  {
    	start:=low
    	end:=high
    	if start>end{
    		return
    	}
    	tmp:=arr[low] //赋值在判断之后
    	for start<end{
    		for start<end&&arr[end][0]>=tmp[0]{
    			end--
    		}
    		arr[start] = arr[end]
    		for start<end&&arr[start][0]<=tmp[0]{
    			start++
    		}
    		arr[end] = arr[start]
    	}
    	arr[start] = tmp
    	fast(arr,low,start-1)
    	fast(arr,start+1,high)
    }
    
    滑动窗口最大值

    leetcode 239 单调栈

    func maxSlidingWindow(nums []int, k int) []int {
    	res:=make([]int,0)
    	que:=make([]int,0)//存储索引值
    	for i:=0;i<len(nums);i++{
    		if len(que)!=0{
    			//超出窗口范围则去除
    			if i-que[0]>=k{
    				que = que[1:]
    			}
    			for len(que)!=0&&nums[i]>=nums[que[len(que)-1]]{
    				que = que[:len(que)-1]
    			}
    		}
    		que = append(que,i)
    		if i+1>=k{
    			res = append(res,nums[que[0]])
    		}
    	}
    	return res
    }
    
    子数组最大累加和 牛客

    连续累加最大和
    全局记录,和<0则归零

    int maxsumofSubarray(vector<int>& arr) {
            if (arr.empty())
                return 0;
            int res = INT_MIN;
            int count = 0;
            for(int i=0;i<int(arr.size());i++)
            {
                 count+=arr[i];
                 res = max(res,count);
                 count = count<0?0:count; //和小于0则归零
            }
            return res;
        }
    
    字符串最长无重复子串长度

    [2,2,3,4,3] 为3
    set存储从左到右

    int maxLength(vector<int>& arr) {
            int n = arr.size();
            if(n==0)return 0;
            int res = 0;
            set<int>hash; //保存,重复则从前向后去除元素,直到没有重复
            int l = 0;
            int r = 0;
            while(r<n)
            {
                if(!hash.count(arr[r]))
                {
                    hash.insert(arr[r]);
                    r++;
                }else{
                    hash.erase(arr[l]);
                        l++;
                }
                res = max(res,int(hash.size()));
            }
            return res;
        }
    
    le11 盛水最多容器

    左右双指针,左右最小的向中间移动,移动时更新最大值

    func maxArea(height []int) int {
    	if len(height)==0{
    		return 0
    	}
    	res:=0
    	l:=0
    	r:=len(height)-1
    	for l<r{
    		tmp:=(r-l)*min(height[l],height[r])
    		res = max(res,tmp)
    		if height[l]>height[r]{
    			r--
    		}else{
    			l++
    		}
    	}
    	return res
    }
    
    func min(x,y int)int  {
    	if x>y{
    		return y
    	}else{
    		return x
    	}
    }
    
    func max(x,y int)int  {
    	if x>y{
    		return x
    	}else{
    		return y
    	}
    }
    
    接雨水

    多种方法解决

    • 双指针

    其他

    合并两个排序链表(递归)
    • 递归
     ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
            if(l1==NULL) return l2;
            if(l2==NULL) return l1;
    
            if(l1->val<l2->val)
            {
                l1->next = mergeTwoLists(l1->next,l2);
                return l1;
            }else{
                l2->next = mergeTwoLists(l1,l2->next);
                return l2;
            }
        }
    
    
    k个排序链表合并

    leetcode 23

    • 分治法
      每次合并两个,将结果放入队列尾部,直到队列只剩下一个
      面试遇到说这个不是最优解的,我感觉优先队列和这个复杂度差不多
    func mergeKLists(lists []*ListNode) *ListNode {
    	if len(lists)==0{
    		return nil
    	}
    	//合并放尾部,去除头部两个,直到队列剩余为1
    	for len(lists)>1{
    		lists = append(lists,merge(lists[0],lists[1]))
    		lists = lists[2:]
    	}
    	return lists[0]
    
    }
    
    //合并两个链表
    func merge(one *ListNode ,two *ListNode)*ListNode  {
    	dummy:=new(ListNode)
    	cur:=dummy
    	for one!=nil&&two!=nil{
    		if one.Val<two.Val{
    			cur.Next = one
    			one = one.Next
    		}else{
    			cur.Next  = two
    			two = two.Next
    		}
    		cur = cur.Next
    	}
    	if one!=nil{
    		cur.Next = one
    	}else{
    		cur.Next = two
    	}
    	return dummy.Next
    }
    
    
    • 优先队列
      手动实现优先队列 我吐了
      虽然标准库有优先队列,还是手动踩坑锻炼下
      调试差点吐了,还是参考下标准库里heap的实现方式吧
    func mergeKLists(lists []*ListNode) *ListNode {
    	if len(lists)==0{
    		return nil
    	}
    
    	var  heap []*ListNode
    	for i:=0;i<len(lists);i++{
    		if lists[i]!=nil{
    			heap = push(heap,lists[i])
    		}
    	}
    	sink(heap,0)//形成堆
    	dummy:=new(ListNode)
    	cur:=dummy
    	for len(heap)!=0{
    		var tmp *ListNode
    		heap,tmp = pop(heap)//取出堆顶
    
    		cur.Next = tmp
    		cur = cur.Next
    		if tmp.Next!=nil{  //非空放入下一个
    			heap = push(heap,tmp.Next)
    		}
    	}
    	return dummy.Next
    }
    
    //节点下沉
    func sink(arr []*ListNode,start int)  {
    	length:=len(arr)-1
    	for{
    		next:=start*2+1
    		if next>length{
    			return
    		}
    		if next+1<=length&&arr[next+1].Val<arr[next].Val{
    			next++
    		}
    		if arr[start].Val<arr[next].Val{
    			break
    		}
    		arr[start],arr[next] = arr[next],arr[start]
    		start = next
    	}
    }
    
    //节点上升只需要找父节点
    func swim(arr []*ListNode,start int){
    	for {
    		parent:=(start-1)/2
    		if start==parent||arr[parent].Val<=arr[start].Val{
    			break
    		}
    		arr[parent],arr[start] = arr[start],arr[parent]
    		start = parent
    	}
    }
    
    //insert
    func push(arr []*ListNode,root *ListNode)[]*ListNode  {
    	//上升节点
    	arr = append(arr,root)
    	swim(arr,len(arr)-1)
    	return arr
    }
    
    //取出优先高的,结尾放头部,减少容量,下沉节点
    func pop(arr []*ListNode)([]*ListNode,*ListNode)  {
    	tmp:=arr[0]
    	arr[0] = arr[len(arr)-1]
    	arr = arr[:len(arr)-1]
    	sink(arr,0)
    	return arr,tmp
    }
    
    //数组创建链表,方便debug
    func Creat(arr []int)*ListNode  {
    	root:=new(ListNode)
    	cur:=root
    	for i:=0;i<len(arr);i++{
    		tmp:=new(ListNode)
    		tmp.Val = arr[i]
    		cur.Next = tmp
    		cur = cur.Next
    	}
    	return root.Next
    }
    
    
    牛客 合并两个有序数组

    从后向前,把B放入A中,不开辟新的空间

     void merge(int A[], int m, int B[], int n) {
            int i = m-1,j = n-1,len = m+n-1;
            while(i>=0||j>=0)
            {
                if((i>=0&&A[i]>=B[j])||j<0)
                    A[len--]=A[i--];
                else{
                    A[len--]=B[j--];
                }
               
            }
        }
    
    lt面试题08.06 汉诺塔问题

    n个数字,a移动到c
    递归问题 时O(2^n) 空O(1)

    func hanota(A []int, B []int, C []int) []int {
    	n:=len(A)
    	move(n,&A,&B,&C)
    	return C
    }
    
    func move(n int,a *[]int, b *[]int,c *[]int)  {
    	if n<=0{
    		return
    	}
    	//a的n-1个经过c移动到b
    	move(n-1,a,c,b)
    	//a上层移动到c
    	*c = append(*c,(*a)[len(*a)-1])
    	*a = (*a)[:len(*a)-1]
    	//b上的n-1个经过a移动到c
    	move(n-1,b,a,c)
    }
    
    leetcode69 x的平方根

    二分法和牛顿法

    • 二分法
    func mySqrt(x int) int {
    	mid:=0
    	l:=0
    	r:=x
    	for l<r{
                    //(l+r+1)这是为了防止当l = r - 1时,出现死循环的情况
    		mid = (l+r+1)>>1
    		if mid*mid<=x{
    			l = mid
    		}else{
    			r = mid-1
    		}
    	}
    	return r
    }
    
    
    • 牛顿法
      主要是迭代公式x = (x + n/x) / 2
    func mySqrt(x int) int {
    	res:=x
    	for res*res>x{
    		res = (res+x/res)/2
    	}
    	return res
    }
    
  • 相关阅读:
    75. 颜色分类
    排序链表
    两个数组的交集
    242. 有效的字母异位词
    排序优化
    622.设计循环队列
    比较含退格的字符串
    682.棒球比赛
    496.下一个更大的元素I
    线性排序算法
  • 原文地址:https://www.cnblogs.com/9527s/p/14351968.html
Copyright © 2011-2022 走看看