题目来源:leetcode/洛谷/(持续更新&&题都很简单的,主要是我太菜)
一.字符串
1.回文字符串:给定一个字符串,验证它是否是回文串,只考虑字母和数字字符,可以忽略字母的大小写。
说明:本题中,我们将空字符串定义为有效的回文串。
示例 1:
输入: “A man, a plan, a canal: Panama”
输出: true
示例 2:
输入: “race a car”
输出: false
核心思想:双指针指向头尾将元素传入判断函数。
bool isPalindrome(char* s) {
if(strlen(s)==0)
return true;
else{
int low=0;
int high=strlen(s)-1;
for(low,high;low!=high;low++,high--)
if(ifSame(s[low],s[high])||ifValidNum(s[low],s[high]))
return true;
else return false;
}
}
bool ifValidChar(char a){
if((a>='A'&&a<='Z')||(a>='a'&&a<='z'))
return true;
else{
return false;
}
}
bool ifValidNum(char a){
if(a>='0'&&a<='9')
return true;
else
return false;
}
//判断字母是否相等(首先判断是否为有效字母)
bool ifSame(char c1,char c2){
if(ifValidChar(c1)&&ifValidChar(c2))
{
if(c1==c2||abs(c1-c2)=='a'-'A') //当两个字符都是有效的则判断1.是否相等 2.是否二者绝对值之差为大小写关系?
return true;
else
return false;
}
return false;
}
最核心的:if(c1c2||abs(c1-c2)‘a’-‘A’) //对于字符相等或互为大小写的判断
再上一个别人写的c++
class Solution {
public:
bool isPalindrome(string s) {
//回文串,正读反读都一样,只考虑字母和数字字符,忽略字母的大小写
if(s=="")
return true;
string tmp;
//将string中的所有字符都转换为小写形式
for(auto&c:s)//对s中的每一个字符
c=tolower(c);//c是引用,因此赋值语句将改变s中的字符值
//将字母和数字字符保存在tmp中
for(int i=0;i<s.size();i++){
if(isalnum(s[i]))
tmp +=s[i];
}
for(int i=0;i<tmp.size();i++){
if(tmp[i]!=tmp[tmp.size()-i-1]){
return false;
}
if(i==(tmp.size()-i-1))
break;
}
return true;
}
};
感觉思路很好,学习一下,但是我c++用的不是特别熟练。
2.字符串转整数(这题用c太麻烦了,直接py)
请你来实现一个 atoi 函数,使其能将字符串转换成整数。
首先,该函数会根据需要丢弃无用的开头空格字符,直到寻找到第一个非空格的字符为止。
当我们寻找到的第一个非空字符为正或者负号时,则将该符号与之后面尽可能多的连续数字组合起来,作为该整数的正负号;假如第一个非空字符是数字,则直接将其与之后连续的数字字符组合起来,形成整数。
该字符串除了有效的整数部分之后也可能会存在多余的字符,这些字符可以被忽略,它们对于函数不应该造成影响。
注意:假如该字符串中的第一个非空格字符不是一个有效整数字符、字符串为空或字符串仅包含空白字符时,则你的函数不需要进行转换。
在任何情况下,若函数不能进行有效的转换时,请返回 0。
说明:
假设我们的环境只能存储 32 位大小的有符号整数,那么其数值范围为 [−231, 231 − 1]。如果数值超过这个范围,qing返回 INT_MAX (231 − 1) 或 INT_MIN (−231) 。
class Solution:
def myAtoi(self, str: str) -> int:
import re
str_strip_no=str.lstrip(' ')
if not str_strip_no:
return 0
str_num=re.search(r'^[+-]?\d+',str_strip_no)
if str_num:
num=int(str_num.group())
if num< -2147483648:
return -2147483648
elif num > 2147483647:
return 2147483647
return int(num)
return 0
根据题意,先lstrip(’ ')去一下字符串头的空格然后判断去完是否为空,然后正则匹配,将匹配出来的字符串group()截获然后转int赋值给num最后判断num范围,注意有符号int在正数时要-1
最后上一个看到的很好的用c把数字字符串转整数的方法:
for(int n=0;isdigit(s[i]);i++)
n=n*10+(s[i]-'0'); //恰好取了个相对于‘0’的差值,但是有一个头文件ctype.h蛮好用的
放个链接:关于ctype.h
3.NOIP普及组:
(1)题面:P1055 ISBN号码
有几个坑1.字符数组跟数字直接做运算是没有意义的但是可以(‘5’-‘0’)*8先把他变成数字
2.同样的,不能直接往字符数组里面赋整形数字但是可以用sprintf()或者itoa()或者1+‘0’(此时1变成‘1’)
3.不过itoa等一众函数貌似只能在win上用sprintf倒是可以跨平台,就是效率略低,上链接sprintf
itoa
(2)题面:铅笔
先上我的代码:
#include<iostream>
using namespace std;
int main()
{
int a,b,c,d,e,f,g;
long long min=1000000000;
int k[3];
int k1[3]={0};//0代表没有被动过
cin>>a>>b>>c>>d>>e>>f>>g;
for(int i=0;;i++)
{
if(b*i>=a&&k1[0]==0)
{
k[0]=c*i;
k1[0]=1;
}
if(d*i>=a&&k1[1]==0)
{
k[1]=e*i;
k1[1]=1;
}
if(f*i>=a&&k1[2]==0)
{
k[2]=g*i;
k1[2]=1;
}
if(k1[1]==1&&k1[2]==1&&k1[0]==1)
{
break;
}
}
for(int i=0;i<3;i++)
{
if(k[i]<=min)
min=k[i];
}
cout<<min;
return 0;
}
核心思想就是用k数组记录每组输入最终的钱数,k1数组用来打标,0是没有动,1是已经动过。必须要保证更新k数组中的元素只更新一次即:每组输入达到超过标准的第一个值就停止。最后min开一个大数找出最小值。(min开大很重要,要不然有些大数据的样例过不去)
是不是看起来很暴力???看看大佬的wp
#include<cstdio>
using namespace std;
int i,j,k,n,m,w,ans;
int main(){
scanf("%d",&n);
for(i=0;i<3;i++){
scanf("%d%d",&j,&k);m=j;w=k;//输入并存下初始的价格与数量
while(j<n){j<<=1;k<<=1;}//价格与数量不断*2直到数量大于n
while(j>n){j-=m;k-=w;}//*2有可能导致买太多了,减去一些
while(j<n){j+=m;k+=w;}//减去之后又可能太少了,加上一些
//其实就是大幅度地上调,然后做一些微调
if(k<ans||ans==0)ans=k;//判断是否是最小花费
}
printf("%d\n",ans);
return 0;//输出并返回
}
tql 核心其实就是用位移caozuo进行大规模的数据增长,到一定程度后再进行调整。
logn级别的时间复杂度