[贝壳找房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,不能保证区间内。
采用滑动窗口的方法:
- 先定义两个指针left和right,均从0开始,作为窗口的左右边界,记区间的左右边界为L和R。
- 遍历数组,扩张窗口的右边界,考察每个元素a[right]为区间右端点的情况。当右边界遍历到某个位置right时,累加a[right]的频数。
- 如果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()
例三:
没做出来