手撕coding

常规手撕题目:

题目一:01背包问题(dp)

给两个数组,w[2,3,5,10]表示每个物品的大小,v[4,1,8,3]表示每个物品对应的价值,然后给一个背包的大小s,然后问能装下的最多的价值。

解题:利用动归,构建一个dp数组,并初始化;
dp数组的改变情况:(1)j< w [i] :那么dp[i][j]=dp[i-1][j];(2)j>=w[i] :那么dp[i][j]=max(dp[i-1][j],dp[i-1][j-w[i]]+v[i])

w=[9,2,1]
v=[1,4,9]
s=10
w.insert(0,0)
v.insert(0,0)
dp=[[0 for _ in range(s+1)] for _ in range(len(w))]
for i in range(1,len(w)):
    for j in range(1,s+1):
        if j<w[i]:
            dp[i][j]=dp[i-1][j]
        else:
            dp[i][j]=max(dp[i-1][j],dp[i-1][j-w[i]]+v[i])
print(dp[-1][-1])

题目二:寻找路径(dfs),可以上下左右

给一个矩阵,寻找是否存在一条路径满足题意;

解题:采用dfs的方式,遍历数组的每个元素,然后dfs,dfs中上下左右移动,并加入一个矩阵标记是否访问过,判断是否满足条件,其中条件有
(1)超过边界;
(2)已经访问过;
(3)不等于所要找的路径元素;
附上代码:

class Solution {
    int d[4][4]={{-1,0},{1,0},{0,-1},{0,1}};
    int rows;
    int cols;
    bool inArea(int x,int y)
    {
        if(x<0 || x>=rows || y<0 || y>=cols)
            return false;
        else
            return true;
    }
    bool dfs(vector<vector<char>>& b,string w,vector<vector<char>>& v,int x,int y,int index)
    {
        if(index==w.length()-1)
            return w[index]==b[x][y];
        if(b[x][y]==w[index])
        {
            v[x][y]=true;
            for(int i=0;i<4;i++)
            {
                int newx=x+d[i][0];
                int newy=y+d[i][1];
                if(inArea(newx,newy)&&!v[newx][newy])
                {
                    bool res=dfs(b,w,v,newx,newy,index+1);
                    if(res)
                        return true;
                }
            }
            v[x][y]=false;
        }
        return false;
    }
public:
    bool exist(vector<vector<char>>& board, string word) {
        rows=board.size();
        if(rows==0)
            return false;
        cols=board[0].size();
        if(cols==0)
            return false;
        vector<vector<char>> visit(rows,vector<char>(cols,false));
        for(int i=0;i<rows;i++)
        {
            for(int j=0;j<cols;j++)
            {
                
                bool res=dfs(board,word,visit,i,j,0);
                if(res)
                    return true;
            }
        }
        return false;
    }
};

问题三:爬楼梯问题(dp)

一次可以爬一阶或者两阶,那么n阶台阶有几种方式到达。

解题:采用动态规划求解
1、确认原问题和子问题;
2、确认状态;
3、确认边界情况;dp[1]=1;dp[2]=2;
4、状态转移方程;dp[i]=dp[i-1]+dp[i-2];

附上代码:

def jump(self,n):
    dp=[0]*n
    if n==1:
        return 1
    dp[0]=1
    if n==2:
        return 2
    dp[1]=2
    for i in range(2,n):
        dp[i]=dp[i-1]+dp[i-2]
    return dp[n-1]

问题四:小偷(bp)

一个小偷,不连续两家偷盗的情况下,最大的价值

解题:采用动态规划求解
1、确认原问题和子问题;
2、确认状态;
3、确认边界情况;dp[1]=a[0];dp[2]=max(a[0],a[1]);
4、状态转移方程;dp[i]=max(dp[i-1],dp[i-2]+a[i]);

附上代码:

def rob(self,nums):
        n=len(nums)
        dp=[0]*n
        if n==0:
            return 0
        if n==1:
            return nums[0]
        dp[0]=nums[0]
        if n==2:
            return max(nums[0],nums[1])
        dp[1]=max(nums[0],nums[1])
        for i in range(2,n):
            dp[i]=max(dp[i-2]+nums[i],dp[i-1])
        return dp[n-1]

问题五:最小的钞票数(dp)

面值为【1、2、5、10】的钞票,求14的组合最少的钞票个数

分析:采用动态规划
1、确认原问题和子问题;
2、确认状态;
3、确认边界情况;dp[0]=0;dp[1]=1];dp[2]=1;
4、状态转移方程;dp[i]=min(dp[i-1],dp[i-2],dp[i-5],dp[i-10])+1

附上代码:

    def coins(self,n,cot):
        dp=[]
        for i in range(cot+1):
            dp.append(-1)
        dp[0]=0
        for i in range(1,cot+1):
            for j in range(len(n)):
                if i-n[j]>=0 and dp[i-n[j]]!=-1:
                    if dp[i]==-1 or dp[i]>dp[i-n[j]]+1:
                        dp[i]=dp[i-n[j]]+1
        return dp[cot]

附上方法二代码:

    def coin(self,n,cot):
        dp=[cot+1]*(cot+1)
        dp[0]=0
        for i in range(cot+1):
            for item in n:
                if item>i:
                    continue
                else:
                    dp[i]=min(dp[i],1+dp[i-item])
        if dp[cot]==cot+1:
            return -1
        else:
            return dp[cot]

问题六:快排(递归)和链表快排(双指针)

对于快排,可以采用递归的方式,也可以采用切片的方式;
附上代码:

def fast(self,nums):
        res=self.quick(nums,0,len(nums)-1)
        return res
    def quick(self,nums,start,end):
        if start<end:
            p=self.position(nums,start,end)
            self.quick(nums,start,p-1)
            self.quick(nums,p+1,end)
        return nums
    def position(self,nums,start,end):
        base=nums[start]
        low,high=start,end
        while low<high:
            while low<high and nums[high]>=base:
                high-=1
            nums[low]=nums[high]
            while low<high and nums[low]<base:
                low+=1
            nums[high]=nums[low]
            nums[low]=base
        return low
    def fast2(self,nums):
        if len(nums)<=1:
            return nums
        else:
            base=nums[0]
            l=[x for x in nums if x<base]
            m=[x for x in nums if x==base]
            r=[x for x in nums if x>base]
            return self.fast2(l)+m+self.fast2(r)

链表快排,只能从头到尾遍历
附上代码:

pNode* partition(pNode* start,pNode* end){
    int num = start->val;
    pNode* p = start;
    pNode* q = start->next;
    while(q != end){
        if(q->val < num){
            p = p->next;
            swap(p->val,q->val);
        }
        q = q->next;
    }
    swap(p->val,start->val);
    return p;
}
void quick_sort(pNode* start,pNode* end){
    if(start != end){
        pNode* index = partition(start,end);
        quick_sort(start,index);
        quick_sort(index->next,end);
    }
}

问题七:全排列(递归)

给[1,2,3],求出全排列,利用递归思想,python中的切片;

附上代码:

    def perm(self,res,nums,temp):
        if len(nums)==0:
            res.append(temp)
            return
        for i in range(len(nums)):
            self.perm(res,nums[:i]+nums[i+1:],temp+[nums[i]])

问题八:格雷码(数学)

给出n为二进制bit,其中相邻的元素,只有唯一一位bit不同;(00 01 11 10)

附上代码:

    def gradCode(self,n):
        res=[]
        i=0
        while i<(1<<n):
            res.append(i^(i>>1))
            i+=1
        return res

问题九:集合的子集(递归)

给一个集合,求子集,去掉重复的子集

附上代码:

    def subset(self,nums):
        res=[]
        temp=[]
        nums.sort()
        def sub(nums,temp,res,cur):
            res.append(temp.copy())
            for i in range(cur,len(nums)):
                if i>cur and nums[i]==nums[i-1]:
                    continue
                temp.append(nums[i])
                sub(nums,temp,res,i+1)
                temp.pop()

        sub(nums,temp,res,0)
        return res
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值