牛客网真题训练记录(一)(python)

[贝壳找房c++工程师笔试卷]:

例一:

在这里插入图片描述
先利用set函数提取出s字符串中出现过的字母,将其变成list类型后sort,直接找出前k个就是需要在S中删除的字母,在S中依次删除即可 s=s.replace(i,“”)

class Solution:
    def NS_String(self , s , k ):
        # write code here
        sset=set(s)
        sset=list(sset)
        sset.sort()
        for i in sset[:k]:
            s=s.replace(i,"")
        return s

在这里插入图片描述

先重温下常用set()函数的使用:

s="caabeefa"
s_set=set(s)

s_set={‘a’, ‘c’, ‘e’, ‘b’, ‘f’}

初始解答:dfs方法

想法很简单,就是循环找s中的ascii码最小的字符,然后都删除
s=list(filter(lambda x : x != tmp,s))
(list和filter的组合使用)
通过了10/11,第11例解答错误,说明还有没想到的测试用例。
本来简单的题,计时的情况下容易手比脑子先动,需要多练练

#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
# 
# @param s string字符串 
# @param k int整型 
# @return string字符串
#
class Solution:
    def NS_String(self , s , k ):
        # write code here
        #找到s中ascii码最小的字符
        def mins(se):
            tmp = float('inf')
            for ch in se:
                if ord(ch) < tmp:
                    tmp = ord(ch)
            return chr(tmp)

        if k <= 0:
            return None
        s = list(s)
        res=[] #记录答案

        def dfs(res,k,s):
            if k<=0:
                res=s
                return res #到了k次,把res返回

            tmp=' '
            for ch in s:
                if ch == mins(s):
                    tmp=ch
                    break
            s=list(filter(lambda x : x != tmp,s)) #删除list s中的所有tmp字符
            res=dfs(res,k-1,s)
            if res: #k为其他时,res为None;只有返回了res时才为True
                return res 
        res=dfs(res,k,s)
        return "".join(res) #list s转str s

例二

在这里插入图片描述

初始解答:循环m次,一次次加(超时)

用一个循环记录每一行加肥料的过程
用一个flag记录正趟还是反趟,cnt记录在哪一行(一共n行),res记录结果
flag1表示是正向,如果是正向,cnt+=1,res[cnt]+=1,到了cntn,flag=0
flag0表示是反向,如果是反向,cnt-=1,res[cnt]+=1,到了cnt1,flag=1

class Solution:
    def FarmerNN(self , n , m ):
        # write code here
        res=[0]*(n+1)
        flag=1 #正向
        cnt=0 #记录在哪个格子
        for i in range(m):
            if flag==1:#如果正向
                cnt+=1
                res[cnt]+=1
                if cnt==n:
                    flag=0
            else:#如果反向
                cnt-=1
                res[cnt]+=1
                if cnt==1:
                    flag=1
        return res[1:n+1]

在这里插入图片描述

第二次解答:寻找规律,一步到位(通过)

画个图模拟一遍施肥的过程,发现可以分成几个段来分段考虑
第一趟跑了n行,其余趟都是n-1行,第一趟给所有行都加上1(当m>n)
考虑第一趟之外的趟数:
第0行在奇数趟时等于 趟数//2+1 ;偶数趟时 趟数//2
第n-1行 趟数//2
第1到n-2行分两步考虑,一个是可以整除的部分[1+cnt]*(n-2),如果有余数再额外加。

比初始解答的时间复杂度大大降低

class Solution:
    def FarmerNN(self , n , m ):
        # write code here
        if n==1:
            return [m]
        if n==2:
            return [m//2+1,m//2]
        res=[0 for _ in range(n)]
        if m<=n:
            res[:m]=[1]*m
            return res
        
        cnt=(m-n)//(n-1) #无人机跑的次数
        left=(m-n)%(n-1) #剩余
        
        if cnt%2==0:
            res[0]=1+cnt//2
            res[n-1]=1+cnt//2
            res[1:n-1]=[1+cnt]*(n-2)
            for i in range((n-2-left+1),((n-2)+1)):
                res[i]+=1
        else:
            res[0]=1+cnt//2+1
            res[n-1]=1+cnt//2
            res[1:n-1]=[1+cnt]*(n-2)
            for i in range(1,left+1):
                res[i]+=1
            
        return res

在这里插入图片描述

例三:奇特区间数

最开始的想法:定义两个for循环
一旦遇到异或等于target的,内层循环break,下一个i继续试;否则奇特空间加1

class Solution:
    def section(self , a , t ):
        # write code here
        #[1,4,10,10,2,8,4,4,2,9],1
        #预期:39
        #实际:44
        n=len(a)
        res=0
        for i in range(n-1):
            for j in range(i+1,n):
                if a[i]^a[j]==t:
                    break
                else:
                    res+=1
        return res 

但是这种方法只能保证区间的初始和结尾值异或不为t,不能保证区间内。

采用滑动窗口的方法:

  1. 先定义两个指针left和right,均从0开始,作为窗口的左右边界,记区间的左右边界为L和R。
  2. 遍历数组,扩张窗口的右边界,考察每个元素a[right]为区间右端点的情况。当右边界遍历到某个位置right时,累加a[right]的频数。
  3. 如果a[right]异或t在哈希表内,说明之前加入的数中存在一个数a[right]异或t,当它作为区间左边界元素时,在a[right]为区间右边界的情况下,会造成

a[L]^a[R]=a[right]^t^a[right]=t,使得[L,R]为非奇特区间
(a[right]^a[right]=0,1^0=1,0^0=0,所以t异或0等于它本身)

此时开始收缩窗口的左边界,直到非奇特区间被排除在外,即a[right]^t不在哈希表内。
5. 如果a[right]^t不在哈希表内,说明[left,right]中都是奇特区间,在right为区间右端点的情况下,从left到right-1都可以作为区间的左端点形成奇特区间,此时有right-left个奇特区间产生,将其累加到奇特区间的总数上。

评论区C++代码:

class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param a int整型vector 
     * @param t int整型 
     * @return long长整型
     */
    long long section(vector<int>& a, int t) {
        // write code here
        unordered_map<int,int> mp;
        long long res=0;
        int l=0,r=0;
        while(r<a.size()){
            mp[a[r]]++;
            while(mp.count(a[r]^t) && mp[a[r]^t]>0){//unordered_map.count(key)	在容器中查找以 key 键的键值对的个数。
 //表示如果a[right]异或t在哈希表内,并且值大于0(至少有一个)
                mp[a[l]]--;
                //收缩左区间直到哈希表中没有a[r]^t
                l++;
            }
            res+=(r-l);
            //扩展右空间
            r++;
        }
        return res;
    }
};

python 3.9版

#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
# 
# @param a int整型一维数组 
# @param t int整型 
# @return long长整型
#
class Solution:
    def section(self , a , t ):
        # write code here
        #[1,4,10,10,2,8,4,4,2,9],1
        #预期:39
        #实际:44
        mydict=dict.fromkeys(a,0)
        n=len(a)
        res=0
        l,r=0,0
        while r<n:
            mydict[a[r]]+=1  #右边界扩宽后更新mydict
            while mydict.__contains__(a[r]^t) and mydict[a[r]^t]>0:#python3 去除了has_key()方法
                #被 __contains__(key) 替代:
                mydict[a[l]]-=1
                l+=1
                
            res+=(r-l)
            r+=1
            
        return res

[深信服软件开发F卷]

例一:
思路:先装完b,再装a。
先计算装完b需要多少个机架,然后这些机架计算装完b后剩余的空间,用来装a。
最后计算剩下的a需要额外多少个机架,加上,得到总共需要的机架数
在这里插入图片描述

T=int(input()) #input的返回都是string类型
S=[[0]*3 for _ in range(T)]
for i in range(T):
    S[i][0],S[i][1],S[i][2]=map(int,input().split())

#input函数输入的都是string,需要先转换成int

#s[i][0]:a s[i][1]:b s[i][2]:h
import math
#对于每个客户
for s in S:
    res=0
#    if s[2]%2==0:#先装2,再装1
#        res+=(math.ceil(s[1]/(s[2]//2))+math.ceil(s[0]/s[2]))
#    else:
    res+=math.ceil(s[1]/(s[2]//2))
        #print(res)
    if (s[2]*res-2*s[1])>=s[0]:
            #print("T")
        res+=0
    else:
        res+=math.ceil((s[0]-(s[2]*res-2*s[1]))/s[2])
    print(res)
        
        

在这里插入图片描述

例二:
在这里插入图片描述
思路:设x是水果实际价格、y是面点实际价格,列出方程式,解二元一次方程。
题目要求
1.若不存在唯一解,unknown(就是得到x和y的式子分母为0)
2.若非正整数,unknown(第二个if判断整数,第三个if判断正数)

T=int(input())
S=[[0]*6 for _ in range(T)]
for i in range(T):
    S[i][0],S[i][1],S[i][2],S[i][3],S[i][4],S[i][5]=map(int,input().split())
    
for s in S:
    if s[0]*s[4]-s[3]*s[1]==0 or s[3]*s[1]-s[0]*s[4]==0:
        print("UNKNOWN")
        continue
    if (s[4]*s[2]-s[5]*s[1])%(s[0]*s[4]-s[3]*s[1])!=0 or (s[3]*s[2]-s[0]*s[5])%(s[3]*s[1]-s[0]*s[4])!=0:
        print("UNKNOWN")
        continue
        #若不存在唯一解,也unknown
    #if s[0]==0
    #if s[3]/s[0]==s[4]/s[1] and s[3]/s[1]==s[5]/s[2]:
       # print("UNKNOWN")
        #continue
    if (s[4]*s[2]-s[5]*s[1])/(s[0]*s[4]-s[3]*s[1])<=0 or (s[3]*s[2]-s[0]*s[5])/(s[3]*s[1]-s[0]*s[4])<=0:
        print("UNKNOWN")
        continue
    print((s[4]*s[2]-s[5]*s[1])//(s[0]*s[4]-s[3]*s[1]),(s[3]*s[2]-s[0]*s[5])//(s[3]*s[1]-s[0]*s[4]))
#    print()


    

在这里插入图片描述

例三:
在这里插入图片描述
没做出来

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值