重复一次的最长子串
在一个字符串中找到最多重复一次的最长子串,并返回子串长度(AC100%)
输入:abcabcbb
输出:6
说明:abcabc是最多重复一次的最长子串
- 该题是3. 无重复字符的最长子串的变体,利用滑动窗口思想,不断更新左右指针,
- 右指针向右跳,并更新窗口的内容
- 若满足
while window[c]>2
,说明该字符开始重复第3次,不满足条件了,因此左指针开始向右跳,并更新窗口内容
s=list(map(str,input().strip().split()))
s=",".join(s)
from collections import defaultdict
window=defaultdict(int)
l,r=0,0
res_max=0
while r<len(s):
c=s[r]
r+=1
window[c]+=1
while window[c]>2:
d=s[l]
l+=1
window[d]-=1
res_max=max(res_max,r-l)
print(res_max)
先按照年月日排序,年月日相同时按照姓名排序,输出姓名
输入:2
zhang san, 1990,1,1
lisi,1991,2,2输出:zhang san, li si
AC 50%
n=int(input())
if n<=0:
print()
res=[]
for i in range(n):
# res.append(input())
res.append(list(map(str,input().strip().split(', '))))
# print(res)
ans=sorted(res,key=lambda x:(x[1],x[2],x[3],x[0]))
# print(ans)
name=[i[0] for i in ans]
name=", ".join(name)
print(name)
# 2
# zhang san, 1985, 12, 31
# li si, 1977, 9, 1
#include <vector>
#include <iostream>
#include <sstream>
#include <algorithm>
using namespace std;
int main() {
int n;
cin >> n;
cin.get(); // 要加这一行,以“吸收”n后面的回车
string line;
string item;
// 构建二维数组
vector<vector<string>> vec;
for (int i = 0; i < n; ++i) {
getline(cin, line);
stringstream ss(line);
vector<string> tmp;
while (getline(ss, item, ', ')) {
tmp.push_back(item);
}
vec.push_back(tmp);
}
// lambda函数进行排序,并保存结果
vector<string> res;
sort(vec.begin(), vec.end(), [](vector<string> &a, vector<string> &b) {
if (a[3] == b[3]) return a[0] < b[0];
if (a[2] == b[2]) return a[3] < b[3];
if (a[1] == b[1]) return a[2] < b[2];
return a[1] < b[1];
});
for (auto &i : vec) {
res.push_back(i[0]);
}
// 打印结果
for (int i = 0; i < res.size(); ++i) {
cout << res[i];
if (i!=res.size()-1){
cout<<", ";
}
}
}
字符串除法
计算第一个字符串中有几个第二个字符串。无需考虑字符串顺序(不知道AC多少)
输入:abcdabcdab bcae
输出:0 (e不在第一个字符串中)
输入:abcdabcdab bca
输出:2 (第一个字符串中有3个b,2个c,3个a。因此第一个字符串中能找到2个第二个字符串)
a,b=list(map(str,input().strip().split()))
from collections import defaultdict
da=defaultdict(int)
db=defaultdict(int)
for i in a:
da[i]+=1
for i in b:
db[i]+=1
# print(da)
# print(db)
res=[]
flag=-1# flag若始终为-1说明b中的key都能在a中找到
for i in db:
if i in da:
tmp=da[i]//db[i]
res.append(tmp) # a中各元素中 有几倍的 b中各元素
else:
flag=0# 若b中的key在a中找不到,则改变flag的值
print(min(res) if flag==-1 else 0)
输出相同或连续子串的个数
如子串 “11121”中,”111” 1个, “11” 2个,”1” 4个, “2” 1个,总共8个
AC 100%
- i从第0个位置遍历到倒数第二个位置,j从i+1处开始遍历
- 若i和j对应的元素相同,则计数+1。否则跳出j的循环,开始下一次i的循环
- 遍历结束后加上最后一个元素
s=str(input())
nums=0
l=len(s)
# i遍历到倒数第二个位置,j从i+1处开始遍历
for i in range(len(s)-1):
nums+=1 #每经过一个元素,+1
x=s[i]
for j in range(i+1,len(s)):
if s[j]==x: # 后面每连续一次,+1
nums+=1
else: # 若不连续,则跳出
break
nums+=1 # 加上最后一个元素
print(nums)
天平平衡
有一堆砝码,天平平衡时,砝码一侧的最大值是多少?
有数组[1,2,3,6]。平衡时,一侧放[1,2,3],另一侧放[6]。结果输出6
背包问题的变体,有点像 LeetCode 416. 分割等和子集。
目前只AC 80% (如[1,2,3,7]这种数组,结果就不对),应该是状态转移方程这里有问题。
nums=list(map(int,input().strip().split(',')))
import math
total=math.floor(sum(nums)/2)
if len(nums)<2:
print(0)
else:
n=len(nums)
dp=[[0 for _ in range(total+1)] for _ in range(n+1)]
for i in range(1,n+1):
for j in range(1,total+1):
if j<nums[i-1]:
dp[i][j]=dp[i-1][j]# 物品太大,超过容量了,装不下
else:
dp[i][j]=max(dp[i-1][j],dp[i-1][j-nums[i-1]]+nums[i-1])# 装或不装的最大值
print(dp)
print(dp[-1][-1])
小测试
n的阶乘末尾含0的个数
- 能生成0,肯定是2*5的组合,其中,2(以及2的倍数)比5的多,所以只要看有几个5
- 25(
5*5
),125(5*5*5
)这种组合,有多个5。所以要不断更新n
要在末尾产生0,则必然是5×2,即使是原数中包含的0也可以分解,因此将题目简化为寻找阶乘中5的个数,即n//5,但是要考虑到这只找到了n中是5倍数的所有数,例如25,即在25!中找到了5个是5的倍数的数分别为5,10,15,20,25,要注意这之中的25依然可以分解为5的倍数,因此n//5其实是少计入了一部分情况的。
要对接下来的这部分情况进行统计,我们可以对n取25的商,即n//25,这样就找到了包含有2个5的数(且因为是对5×5取商,没有重复计入),依此类推,可以循环对n取5, 25, 125…的商,将所有的情况都包括,最终将所有的商汇总即0的个数。
n // 25 == n // 5 // 5,因此可以对n循环取5的商,其效果是一样的。
class Solution:
def trailingZeroes(self, n):
num = 0
while n > 0:
num += n // 5 # 找到5的倍数
n = n // 5 # 重新更新n,继续找,直到没有5的倍数
return num
不要算出阶乘的结果后才统计(以下方法不推荐)
n=int(input())+1
dp=[1 for i in range(n)]
for i in range(1,n):
dp[i]=dp[i-1]*i
res=dp[-1]
res=str(res)
count=0
for j in range(len(res)-1,-1,-1):
if res[j]=='0':
count+=1
else:
break
print(count)