https://blog.csdn.net/bitcarmanlee/article/details/124815289
auto j=min_element(hash.begin(),hash.end());//返回最小key对应的pair的迭代器
cout<<j->first<<endl;//输出最小的key值
cout<<j->second<<endl;//输出最小的key值对应的value
auto j=max_element(hash.begin(),hash.end());//返回最大key对应的pair的迭代器
/*找最大value对应的元素*/
bool cmp_value(const pair<char, int> left,const pair<char,int> right)
{
return left.second > right.second;//大于符号,表示找最大的,pair根据实际情况换
}
auto j=min_element(hash.begin(),hash.end(),cmp_value);//返回最大value对应的pair的迭代器
/*找最小value对应的元素*/
bool cmp_value(const pair<char, int> left,const pair<char,int> right)
{
return left.second <right.second;//小于符号,表示找最小的
}
auto j=min_element(hash.begin(),hash.end(),cmp_value);//返回最小key对应的pair的迭代器,注意最大最小都用min_element
map自动按升序,如果key是字符,按ascii码,如果是字符串,按字符串大小规则
(1)**按key降序排序(**也可以直接用map,然后用栈反转)
将哈希表放进vector,再自己定义比较函数
bool mycompare_func(const pair<char, int> &a, const pair<char, int> &b) {
/* return a.second
if (a.firtt==b.first) return a.second<b.second;
/* 这里表示谁的first更大,谁排前面,也就是整个vector按first的从大到小排列*/
else return a.first>b.first;
}
unordered_map<char, int> m;//定义哈希表
...//自己按照需要填充哈希表
vector<pair<char, int>> v(m.begin(), m.end());//将哈希表拷贝到vector
sort(v.begin(), v.end(), mycompare_func);//按first从大到小排序排序
for(auto it=v.begin(); it!=v.end(); it++) {//遍历输出vector
cout<<it->first;
}
(2)按second降序排序
将哈希表放进vector,再自己定义比较函数
bool mycompare_func(const pair<char, int> &a, const pair<char, int> &b) {
/* return a.first
if (a.second==b.second) return a.first<b.first;
/* 这里表示谁的second更大,谁排前面,也就是整个vector按second的从大到小排列*/
else return a.second>b.second;
}
unordered_map<char, int> m;//定义哈希表
...//自己按照需要填充哈希表
vector<pair<char, int>> v(m.begin(), m.end());//将哈希表拷贝到vector
sort(v.begin(), v.end(), mycompare_func);//按second从大到小排序排序
for(auto it=v.begin(); it!=v.end(); it++) {//遍历输出vector
cout<<it->first;
}
(3)按second升序排序
将哈希表放进vector,再自己定义比较函数
bool mycompare_func(const pair<char, int> &a, const pair<char, int> &b) {
if (a.second==b.second) return a.first<b.first;
else return a.second<b.second;
}
unordered_map<char, int> m;//定义哈希表
...//自己按照需要填充哈希表
vector<pair<char, int>> v(m.begin(), m.end());//将哈希表拷贝到vector
sort(v.begin(), v.end(), mycompare_func);//按second从小到大排序排序
for(auto it=v.begin(); it!=v.end(); it++) {//遍历输出vector
cout<<it->first;
}
在输入的时候额外创建一个vector来存放输入顺序,输出时按这个vector为索引输出哈希,具体看:
候选人票数的统计 华牛 HJ94 easy 按输入顺序输出哈希 map操作
https://blog.csdn.net/shetougong/article/details/112627169
答:https://blog.csdn.net/u010141928/article/details/78671603
答:
//返回最后一个元素
last=*(v.end()-1);//注意end是指向不存在的元素
//删除最后一个元素
v.pop_back();
或者
v.erase(v.end()-1);//end会自动更新
https://blog.csdn.net/wang1997hi/article/details/78364755
double avg=0,sum=0;//注意两个都要是浮点型,不然会发生隐式的类型转换
avg=sum/cnt_pos;
cout<<fixed<<setprecision(1)<<avg<<endl;//括号里是几就保留几位
}
如果是对某个链表进行操作,然后返回该链表,记得创建哑节点dummy
如果输出的结果是一个新的链表,一般需要用head tail,然后if(!head)else,防止最后多创建一个节点
递归一定要记得剪枝,用一个数组保存重复出现的值
return stack.top()时注意不要指向空指针
注意不能在类中定义vector,类内可以定义数组,在类外定义和初始化vector,类里面可以用
二分查找全是细节,一定要写熟练。第一个细节是如何中止二分(左边界小于等于右边界),第二个细节是每次查找如何调整左右边界(原则是新的左右边界一定要包含目标值,目标值可以在新边界的端点)
c++中字符数组用cout输出时,数组必须以’\0’结尾
ASCII字典第一个是空NULL,不是’ ',大写字母从65到90,小写字母从97到122,相差32。
栈 vector都可以存储string,sort函数可以对string进行排序。
#include
using namespace std;
int main(){
int n,square=0,cnt=0;cin>>n;
if(n==0){
cout<<1<<endl;
return 0;
}
while(n>0){
square=pow(n,2);
int tmp=10;
while(square*10>=tmp){
if(square%tmp==n){
cnt++;
break;
}
tmp=10*tmp;
}
n--;
}
cout<<cnt+1<<endl;
}
#include
using namespace std;
int main() {
string s,res;
getline(cin,s);
int len=s.size(),cnt=0;
for(int i =0;i<len;i++){
if(isdigit(s[i])&&cnt==0){
cnt++;
res+='*';
res+=s[i];
}
else if(!isdigit(s[i])&&cnt>0){
res+='*';
res+=s[i];
cnt=0;
}
else
res+=s[i];
}
if(isdigit(s[len-1]))
res+='*';
cout<<res<<endl;
return 0;
}
#include
using namespace std;
int main(){
int ascii[26]={0};
string s,t;
getline(cin,s);
getline(cin,t);
int lent=t.size();
int lens=s.size();
for(int i=0;i<lent;i++){
ascii[t[i]-'a']++;
}
for(int i=0;i<lens;i++){
if(ascii[s[i]-'a']>0)
continue;
else{
cout<<"false"<<endl;
return 0;
}
}
cout<<"true"<<endl;
return 0;
}
#include
using namespace std;
int main(){
int year,month,day,res=0;
cin>>year>>month>>day;
int list[] ={31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366};
if (month == 1)
res = day;
else if((year%4==0&&year%100!=0)||(year%400==0))
res= list[month - 2] + day;
else
res = list[month - 2] + day - 1;
cout<<res<<endl;
return 0;
}
#include
using namespace std;
int main(){
string s;
getline(cin,s);
int len=s.size(),cnt1=0,cnt2=0,cnt3=0,cnt4=0;
for(int i=0;i<len;i++){
if(isalpha(s[i]))
cnt1++;
else if(s[i]==' ')
cnt2++;
else if(isdigit(s[i]))
cnt3++;
else
cnt4++;
}
cout<<cnt1<<endl<<cnt2<<endl<<cnt3<<endl<<cnt4<<endl;
return 0;
}
#include
using namespace std;
int main() {
int a,more=0,res=0;
while(cin>>a&&a!=0){
while(a/3!=0){
res+=a/3;//这次换的汽水
more+=a%3;//不足三个的汽水
a=a/3+ more;//喝完空出来的汽水加上之前不足的
more=0;//把不足的清0
}
more+=a%3;
if(more==2){//只有不足的为2时,才能借一个空气瓶
res++;
}
cout<<res<<endl;
res=0;
more=0;
}
return 0;
}
#include
#include
using namespace std;
int main(){
string s;
getline(cin,s);
int len=s.size();
char res[len+1];
for(int i=0;i<len;i++){
if(s[i]>=97&&s[i]<=99){//小写字母abc
res[i]='2';
}
else if(s[i]>=100&&s[i]<=102){
res[i]='3';
}
else if(s[i]>=103&&s[i]<=105){
res[i]='4';
}
else if(s[i]>=106&&s[i]<=108){
res[i]='5';
}
else if(s[i]>=109&&s[i]<=111){
res[i]='6';
}
else if(s[i]>=112&&s[i]<=115){
res[i]='7';
}
else if(s[i]>=116&&s[i]<=118){
res[i]='8';
}
else if(s[i]>=119&&s[i]<=122){
res[i]='9';
}
else if(s[i]>=65&&s[i]<=89){//大写字母
res[i]=s[i]+33;
}
else if(s[i]==90){//大写字母Z
res[i]='a';
}
else{
res[i]=s[i];
}
}
res[len]='\0';
cout<<res<<endl;
return 0;
}
题解:cin和cout有自己的格式化操作,在输入输出前加hex,表示后续这个是十六进制的数,在输入输出前加dec,表示后续这个是十进制的数,我们可以利用这个原理让输出的变成十六进制数,输出成十进制数。
#include
using namespace std;
int main(){
int res = 0;
while(cin >> hex >> res) //hex表示读入十六进制数
cout << dec << res << endl; //dec表示输出十进制数
return 0;
}
题解:注意字符数组需要多创建一位,存放\0。
#include
#include
#include
using namespace std;
int main() {
string s;
getline(cin,s);
int len=s.size(),i=0,cnt=0;
vector<char>arr;
for(int i=0;i<len;i++){
if(s[i]!=' '){
arr.push_back(s[i]);
}
}
int newlen=arr.size();
char ans[9];
for(i=0;i<newlen;i++){
if(i%8==7){
ans[i%8]=arr[i];
ans[8]='\0';
cout<<ans<<endl;
cnt++;
}
ans[i%8]=arr[i];
}
int more=newlen-8*cnt;
if(more!=0){
for(i=more;i<8;i++){
ans[i]='0';
}
ans[8]='\0';
cout<<ans<<endl;
}
return 0;
}
题解:注意不区分大小写如何处理。首先ASCII字典第一个是空NULL,不是’ ',大写字母从65到90,小写字母从97到122,相差32。
#include
#include
using namespace std;
int main(){
string s;
getline(cin,s);
char target;
cin>>target;
int arr[128]={0};
int len=s.size(),ans=0;
for(int i=0;i<len;i++){
arr[s[i]-NULL]++;
}
if((target-NULL)>=65&&(target-NULL)<=90){
ans=arr[target-NULL]+arr[target-NULL+32];
}
else if((target-NULL)>=97&&(target-NULL)<=122){
ans=arr[target-NULL]+arr[target-NULL-32];
}
else{
ans=arr[target-NULL];
}
cout<<ans<<endl;
return 0;
}
题解: 原题是超过一半,这样可以排序然后取中值,如果改成三分之一,可以用hash记录每个数组项目出现的次数,如果改成出现次数最多的数字,排序和哈希都不太好弄,可以用摩尔投票法,或者叫极限一换一
class Solution {
public:
int majorityElement(vector<int>& nums) {
int res = 0, count = 0;
for(int i = 0; i < nums.size(); i++){
if(count == 0){
res = nums[i];
count++;
}
else
res==nums[i] ? count++:count--;
}
return res;
}
};
题解: 时间100%
class Solution {
public:
int lengthOfLongestSubstring(string s) {
vector<int> m(128,0);//这个容器为了存当遇到相同的字符(假设是a)时i应该变成的值,即前面那个a的下一个字符
int ans=0; //最终的子串长度
int i=0;
for(int j=0;j<s.size();j++){
i=max(i,m[s[j]]);//如果遇到了相同的字符(假设为a),此时m[s[j]]会又去到同样的存储单元m[a的ASCII码值],因为之前遇到a时已经将这个位置的值改成前面那个a的下一个位置了,所以m[s[j]]大于i,将i更新
m[s[j]]=j+1;//更新这个位置的值,当下次再遇到该字母时,将i调整到该字母下一个位置的地方
ans=max(ans,j-i+1);//更新最终结果值,即没相同字母的子串的字符个数
}
return ans;
}
};
题解1: 其实可以直接用库函数
return s.replace(" ","%20");
题解2: 数空格个数,新建一个数组
class Solution {
public:
string replaceSpace(string s) {
int i=0,j=0,cnt=0,len=s.size(),newlen=0;
while(i<len){
if(s[i]==' ')
cnt++;
i++;
}
newlen=len+2*cnt;
char* newstring=new char[newlen+1];
i=0;
while(i<len){
if(s[i]==' '){
newstring[j]='%';
newstring[j+1]='2';
newstring[j+2]='0';
j+=3;
i++;
}
else{
newstring[j]=s[i];
j++;
i++;
}
}
newstring[newlen]='\0';
return newstring;
}
};
题解: 这种方法扩展开,不管想找出现几次的都行,这一类题都可以搞定
class Solution {
public:
char firstUniqChar(string s) {
vector<int> m(26,0);
int i=0,len=s.size();
for(i=0;i<len;i++){
m[s[i]-'a']++;
}
for(i=0;i<len;i++){
if(m[s[i]-'a']==1)
return s[i];
}
return ' ';
}
};
题解1: 运行报错,说访问空指针,不明白为什么
class Solution {
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
int more=0,n1=0,n2=0;
ListNode * ans= new ListNode();
ListNode * cur= ans;
while(l1||l2){
n1=l1? l1->val:0;
n2=l2? l2->val:0;
cur->val=(n1+n2+more)%10;
more=(n1+n2+more)/10;
if(l1->next!=nullptr||l2->next!=nullptr){//就是这里报错,这里加条件是为了防止创建多余的节点
cur->next=new ListNode();
cur=cur->next;
}
if(l1){
l1=l1->next;
}
if(l2){
l2=l2->next;
}
}
if(more>1){
cur->next=new ListNode(more);
}
return ans;
}
};
题解2: 将节点创建整体往后拉一个序号,注意这种方法,输出的结果需要创建一个新链表时,这样非常有用
class Solution {
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
ListNode *head = nullptr, *tail = nullptr;//用于存放结果的链表的头尾指针
int carry = 0;//存放进位的数
while (l1 || l2) {
int n1 = l1 ? l1->val: 0;
int n2 = l2 ? l2->val: 0;
int sum = n1 + n2 + carry;
if (!head) {
head = tail = new ListNode(sum % 10);
} else {
tail->next = new ListNode(sum % 10);
tail = tail->next;
}
carry = sum / 10;
if (l1) {
l1 = l1->next;
}
if (l2) {
l2 = l2->next;
}
}
if (carry > 0) {
tail->next = new ListNode(carry);
}
return head;
}
};
class Solution {
public:
ListNode* deleteNode(ListNode* head, int val) {
ListNode* dummy=new ListNode();
dummy->next=head;
ListNode* cur=dummy;
while(cur->next){//这里一定得cur->next
if(cur->next->val==val){
cur->next=cur->next->next;
return dummy->next;//这里一定得返回
}
else{
cur=cur->next;
}
}
return dummy->next;
}
};
class Solution {
public:
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
ListNode* p1=l1,*p2=l2,*dummy=new ListNode();
ListNode* cur=dummy;
if(!p1||!p2){
return p1? p1:p2;
}
while(p1&&p2){
if(p1->val<p2->val){
cur->next=p1;//这里必须用next
p1=p1->next;
}
else{
cur->next=p2;
p2=p2->next;
}
cur=cur->next;
}
cur->next=p1? p1:p2;
return dummy->next;
}
};
#include
using namespace std;
int main(){
char input; int x=0,y=0;
string s; vector<string> v;
while(cin>>input){
if(input==';'){
v.emplace_back(s);
s.clear();
}
else
s+=input;
}
int len=v.size();
for(int i=0;i<len;i++){
if(v[i][0]=='A'||v[i][0]=='W'||v[i][0]=='S'||v[i][0]=='D'){
if(v[i].size()==3&&isdigit(v[i][1])&&isdigit(v[i][2])){
int tmp1=(int)(v[i][1]-'0');
int tmp2=(int)(v[i][2]-'0');
int tmp=10*tmp1+tmp2;
if(v[i][0]=='A')
x-=tmp;
if(v[i][0]=='W')
y+=tmp;
if(v[i][0]=='S')
y-=tmp;
if(v[i][0]=='D')
x+=tmp;
}
if(v[i].size()==2&&isdigit(v[i][1])){
int tmp=(int)(v[i][1]-'0');
if(v[i][0]=='A')
x-=tmp;
if(v[i][0]=='W')
y+=tmp;
if(v[i][0]=='S')
y-=tmp;
if(v[i][0]=='D')
x+=tmp;
}
}
}
cout<<x<<","<<y<<endl;
}
解法一:暴力解法,用到字符字串substr
#include
using namespace std;
int main(){
string s;
while(cin >> s){
if(s.length() <= 8){ //长度不超过不可行
cout << "NG" << endl;
continue;
}
int flag[4] = {0};
for(int i = 0; i < s.length(); i++){
if(s[i] >= 'A' && s[i] <= 'Z') //大写字母
flag[0] = 1;
else if(s[i] >= 'a' && s[i] <= 'z') //小写字母
flag[1] = 1;
else if(s[i] >= '0' && s[i] <= '9') //数字
flag[2] = 1;
else //其他符号
flag[3] = 1;
}
if(flag[0] + flag[1] + flag[2] + flag[3] < 3){ //符号少于三种
cout << "NG" << endl;
continue;
}
bool repute = false; //记录重复子串
for(int i = 0; i <= s.length() - 6; i++) //遍历检查是否有长度为3的相同的字串
for(int j = i + 3; j < s.length()-3; j++)
if(s.substr(i, 3) == s.substr(j, 3)){
repute = true;
break;
}
if(repute) //有重复
cout << "NG" << endl;
else
cout << "OK" << endl;
}
return 0;
}
#include
using namespace std;
int temp[31]={0};
int tuzi(int n){
if(temp[n])
return temp[n];
if(n<=2)
return 1;
else {
temp[n]=tuzi(n-1)+tuzi(n-2);
return temp[n];
}
return -1;
}
int main(){
int n;
cin>>n;
int res=tuzi(n);
cout<<res;
return 0;
}
题解1:记忆递归,纯递归会超时
vector<int> arr(101);
class Solution {
public:
int fib(int n) {
if(n==0){
return 0;
}
else if(n==1){
return 1;
}
else{
if(arr[n]!=0){
return arr[n];
}
else{
arr[n]=(fib(n-1)+fib(n-2))%1000000007;
return arr[n];
}
}
return -1;
}
};
题解2:动态规划
class Solution {
public:
int f[3];
int fib(int n) {
f[0]=0;f[1]=1;
for(int i=2;i<=n;i++){
f[i%3]=(f[(i-1)%3]+f[(i-2)%3])%1000000007;
}
return f[n%3];
}
};
题解1: 动态规划或者分治法,待刷
题解1: 动态规划,待刷
题解:这道题跟HJ13基本一样
#include
using namespace std;
int main(){
string s,temp;
stack<string>stk;
getline(cin,s);
int cnt=0;
int len=s.size();
for(int i=0;i<len;i++){
if(islower(s[i])||isupper(s[i])){
temp+=s[i];
}
else if(!temp.empty()){
stk.push(temp);
temp.clear();
}
}
if(!temp.empty())
stk.push(temp);
while(!stk.empty()){
cout<<stk.top()<<' ';
stk.pop();
}
return 0;
}
题解: 一是栈可以放string,而是string不能像数组那样每个s[i]单独赋值
#include
using namespace std;
int main(){
string s;
getline(cin,s);
stack<string>stk;
string res;
int i=0,len=s.size();
for(i=0;i<len;i++){
if(s[i]==' '){
stk.push(res);
res.clear();
}
else if(i==len-1){
res+=s[i];//这里原本是res[j]=s[i],这样不可以,res+=s[i]是string加字符字面值,这个用法在C++primer 80
stk.push(res);
res.clear();
}
else{
res+=s[i];
}
}
while(!stk.empty()){
cout<<stk.top()<<' ';
stk.pop();
}
return 0;
}
#include
using namespace std;
int main() {
int a;
cin>>a;
stack<char> stk;
string s;
s=to_string(a);
int len=s.size();
for(int i=0;i<len;i++){
stk.push(s[i]);
}
int j=0;
while(!stk.empty()){
s[j]=stk.top();
stk.pop();
j++;
}
cout<<s<<endl;
return 0;
}
题解:还有一种快慢指针的手法,ACM模式,多组输入
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode* dummy = new ListNode(0, head);//创建哑节点
stack<ListNode*> stk;//创建一个存放ListNode*的栈
ListNode* cur = dummy;
while (cur) //将包括哑节点在内的所有节点都压入栈
{
stk.push(cur);
cur = cur->next;
}
for (int i = 0; i < n; ++i) //弹出后n个节点,注意C++中POP操作并不返回值
{
stk.pop();
}
ListNode* prev = stk.top();
prev->next = prev->next->next;
ListNode* ans = dummy->next;
//这里换成ListNode* ans = head;会报错,不知道为什么,链表操作都按这个固定范式来就行
delete dummy;
return ans;
}
};
class Solution {
public:
vector<int> reversePrint(ListNode* head) {
stack<int>stk;
ListNode* cur=head;
vector<int>ans;
int temp=0;
while(cur){
stk.push(cur->val);
cur=cur->next;
}
while(!stk.empty()){
temp=stk.top();
stk.pop();
ans.push_back(temp);
}
return ans;
}
};
题解1: 栈,栈中存放指针,而不是数据,这样不管数据是啥都可以操作
class Solution {
public:
ListNode* reverseList(ListNode* head) {
if(head==nullptr)
return head;
ListNode* cur=head;
ListNode* temp,*res;
int cnt=0;
stack<ListNode *>stk;
while(cur){
stk.push(cur);
cur=cur->next;
}
while(!stk.empty()){
temp=stk.top();
if(cnt==0){
cnt++;
res=stk.top();
}
stk.pop();
if(!stk.empty())
temp->next=stk.top();
}
temp->next=nullptr;
return res;
}
};
题解2: 双指针,这种方法是在原链表上修改的,如果题目要求不能引入额外空间,就只能这种方法
struct ListNode* reverseList(struct ListNode* head) {
struct ListNode* prev = NULL;
struct ListNode* next;
while (head) {
next= head->next;
head->next = prev;
prev = head;
head = next;
}
return prev;
}
题解3: 头插法建立一个新链表
struct ListNode* reverseList(struct ListNode* head) {
struct ListNode* new = (struct ListNode*)malloc(sizeof(struct ListNode));
new->next=NULL;
while (head) {
struct ListNode* p = (struct ListNode*)malloc(sizeof(struct ListNode));
p->val=head->val;
p->next=new->next;
new->next=p;
head=head->next;
}
return new->next;
}
class Solution {
public:
bool isValid(string s) {
stack<char>stk;
int i=0,len=s.size(),left=0,right=0;
if(len%2==1)
return false;
while(i<len){
if(s[i]=='('||(s[i]=='{'||(s[i]=='[')))
{
stk.push(s[i]);
left++;
}
else{
right++;
if(stk.empty())
return false;
else if(s[i]==')'&&stk.top()=='(')
stk.pop();
else if(s[i]=='}'&&stk.top()=='{')
stk.pop();
else if(s[i]==']'&&stk.top()=='[')
stk.pop();
else
return false;
}
i++;
}
if(left!=right)
return false;
return true;
}
};
class CQueue {
private:
stack<int>instack,outstack;
int temp;
public:
CQueue() {
}
void appendTail(int value) {
instack.push(value);
}
int deleteHead() {
if(outstack.empty()){
if(instack.empty()){
return -1;
}
while(!instack.empty()){
outstack.push(instack.top());
instack.pop();
}
temp=outstack.top();
outstack.pop();
return temp;
}
else{
temp=outstack.top();
outstack.pop();
return temp;
}
return -1;
}
};
class MinStack {
private:
stack<int>instk,minstk;
int curmin=0;
public:
MinStack() {
minstk.push(INT_MAX);//这句话必须加,不然下面return minstk.top()会报错
//初始化最小栈的栈顶元素为最大值为了防止top访问空指针报错
//为什么只加minstk不加instk呢,是因为top函数之前肯定有push函数,push会填充instk,不用担心instk访问空指针
//而调用min函数时,不一定之前调用了push,minstk不一定有数据
}
void push(int x) {
if(instk.empty()){
curmin=x;
instk.push(x);
minstk.push(curmin);
}
else if(x<=curmin){
curmin=x;
instk.push(x);
minstk.push(curmin);
}
else{
instk.push(x);
}
}
void pop() {
if(instk.top()==curmin){
instk.pop();
minstk.pop();
curmin=minstk.top();
}
else{
instk.pop();
}
}
int top() {
return instk.top();
}
int min() {
return minstk.top();
}
};
题解1: hash map
class Solution {
public:
int lengthOfLongestSubstring(string s) {
if(s.size()==0)
return 0;
unordered_map<char,int> hash;
int head=0,tail=0,ans=0,len=s.size();
while(tail<len){
hash[s[tail]]++;
if(hash[s[tail]]==2){
hash[s[tail]]--;
hash[s[head]]--;
ans=max((tail-head),ans);
head++;
}
else{
tail++;
ans=max((tail-head),ans);//这里别忘了
}
}
return ans;
}
};
题解2: hash set
class Solution {
public:
int lengthOfLongestSubstring(string s) {
if(s.size() == 0) return 0;
unordered_set<char> hash;
int head=0,tail=0,ans=0,len=s.size();
while(tail<len){
if(hash.find(s[tail]) != hash.end()){
hash.erase(s[head]);
ans = max(ans,tail-head);
head ++;
}
else{
hash.insert(s[tail]);
tail++;
ans = max(ans,tail-head);
}
}
return ans;
}
};
#include
using namespace std;
int main() {
int size1,size2,a,i=0;
vector<int> vec;
cin>>size1;
while(i<size1){
cin>>a;
vec.emplace_back(a);
i++;
}
i=0;
cin>>size2;
while(i<size2){
cin>>a;
vec.emplace_back(a);
i++;
}
sort(vec.begin(),vec.end());
vec.erase(unique(vec.begin(),vec.end()),vec.end());
int len=vec.size();
for(i=0;i<len;i++){
cout<<vec[i];
}
return 0;
}
题解: 注意sort函数也可以对string进行排序。
#include
#include
#include
using namespace std;
int main(){
vector<string> vec;
int n;
cin>>n;
string s;
while(cin>>s){
vec.emplace_back(s);
}
sort(vec.begin(),vec.end());
int len=vec.size();
for(int i=0;i<len;i++){
cout<<vec[i]<<endl;
}
}
题解: 直接快排,注意快排的函数语法,这道题也可以用哈希和摩尔投票法
class Solution {
public:
int majorityElement(vector<int>& nums) {
sort(nums.begin(),nums.end());
return nums[nums.size()/2];
}
};
题解: 快排,再循环输出
class Solution {
public:
vector<int> getLeastNumbers(vector<int>& arr, int k) {
sort(arr.begin(),arr.end());
vector<int> ans;
for(int i=0;i<k;i++){
ans.push_back(arr[i]);
}
return ans;
}
};
class Solution {
public:
int minArray(vector<int>& numbers) {
int left=0,right=numbers.size()-1,mid=0;
while(left<right){
mid=left+(right-left)/2;
if(numbers[mid]<numbers[right]){
right=mid;
}
else if(numbers[mid]>numbers[right]){
left=mid+1;
}
else{
right--;
}
}
return numbers[left];
}
};
题解: 将数组一分为二,其中一定有一个是有序的,另一个可能是有序,也能是部分有序。
此时有序部分用二分法查找。无序部分再一分为二,其中一个一定有序,另一个可能有序,可能无序。就这样循环.
class Solution {
public:
int search(vector<int>& nums, int target) {
int left=0,len=nums.size(),mid=0;
int right=len-1;
if(len==0){
return -1;
}
if(len==1){
return nums[0]==target? 0:-1;
}
while(left<=right){
mid=left+(right-left)/2;
if(nums[mid]==target){//这个放到最先来判断,节省时间
return mid;
}
if(nums[left]<=nums[mid]){//左边是有序的
if(target>=nums[left]&&target<nums[mid]){//目标值在左边有序数组中
right=mid-1;//调整右边界
}
else{
left=mid+1;//目标值不在左边有序数组中,在右边无序数组,调整左边界
}
}
else{//右边是有序的
if(target>nums[mid]&&target<=nums[right]){
left=mid+1;
}
else{
right=mid-1;
}
}
}
return -1;
}
};
class Solution {
public:
vector<int> searchRange(vector<int>& nums, int target) {
int len=nums.size();
int left=0,right=len-1,mid=0,i=0;
if(len==0){
return {-1,-1};
}
if(len==1){
if(nums[0]==target)
return{0,0};
else
return{-1,-1};
}
while(left<=right){
mid=left+(right-left)/2;
if(nums[mid]==target){
break;
}
if(nums[mid]<target){
left=mid+1;
}
else{
right=mid-1;
}
}
if(nums[mid]!=target){
return {-1,-1};
}
while((mid-i)>=0&&nums[mid-i]==target){
i++;
}
left=mid-i+1;
i=0;
while((mid+i)<len&&nums[mid+i]==target){
i++;
}
right=mid+i-1;
return{left,right};
}
};
#include
using namespace std;
string getfilename(string filepath){ //题取文件名
string res = "";
for(int i = filepath.length() - 1; i >= 0; i--){ //逆向查找到第一个斜杠
if(filepath[i] == '\\')
break;
res = filepath[i] + res; //将字符加到字符串前面
}
if(res.length() > 16) //长度大于16的时候,截取后16位
res = res.substr(res.length() - 16, 16);
return res;
}
int main(){
string filepath, num; //把路径和行号都当成字符串
unordered_map<string, int> mp;
vector<string> res(8, "");
int index = 0; //记录下标
while(cin >> filepath >> num){
string file = getfilename(filepath);
string key = file + " " + num;
if(mp.find(key) == mp.end()){ //没有出现过,需要添加到哈希表中
mp[key] = 1;
res[index] = key;
index = (index + 1) % 8; //循环记录
}else
mp[key]++; //遇到相同的错误,计数增加
}
for(int i = 0; i < 8; i++){
if(res[index] != "") //只输出有记录的,防止不足8个
cout << res[index] << " " << mp[res[index]] << endl;
index = (index + 1) % 8;
}
return 0;
}
#include
using namespace std;
bool mycompare_func(const pair<char, int> &a, const pair<char, int> &b) {
if (a.second==b.second) return a.first<b.first;
else return a.second<b.second;
}
int main(){
int n,i=1; cin>>n;
unordered_map<int, int> hash;
while(n){
if(hash.find(n%10)==hash.end())
hash[n%10]=i;
i++;
n=n/10;
}
vector<pair<int, int>> v(hash.begin(), hash.end());//将哈希表拷贝到vector
sort(v.begin(), v.end(), mycompare_func);//按second从小到大排序排序
int len=v.size()-1,ans=0;
for(auto it=v.begin(); it!=v.end(); it++) {//遍历输出vector
ans+=it->first*pow(10,len);
len-=1;
}
cout<<ans<<endl;
return 0;
}
#include
using namespace std;
bool mycompare_func(const pair<char, int> &a, const pair<char, int> &b) {
/*return a.first
if (a.second==b.second) return a.first<b.first;
else return a.second>b.second;
}
int main(){
string s;getline(cin,s);
unordered_map<char, int> m;
int len=s.size();
for(int i=0;i<len;i++){
m[s[i]]++;
}
vector<pair<char, int>> v(m.begin(), m.end());
sort(v.begin(), v.end(), mycompare_func);
for(auto it=v.begin(); it!=v.end(); it++) {
cout<<it->first;
}
return 0;
}
#include
using namespace std;
int main() {
int n_wait,i=0;cin>>n_wait;
map<string,int> map_wait;
string s_wait;
vector<string> vec_wait;
while(i<n_wait){
cin>>s_wait;
vec_wait.emplace_back(s_wait);
map_wait.insert(make_pair(s_wait,0));
i++;
}
map_wait.insert(make_pair("Invalid",0));
int n_vote;cin>>n_vote;i=0;
vector<string> vec_votes;
string s_vote;
while(i<n_vote){
cin>>s_vote;
vec_votes.emplace_back(s_vote);
i++;
}
int len=vec_votes.size();
for(int i=0;i<len;i++){
auto it=map_wait.find(vec_votes[i]);
if(it!=map_wait.end()){
it->second++;
}
else{
map_wait["Invalid"]++;
}
}
for(int i=0;i<n_wait;i++){//注意这里,完成了按照输入顺序输出哈希
cout<<vec_wait[i]<<" : "<<map_wait[vec_wait[i]]<<endl;
}
cout<<"Invalid"<<" : "<<map_wait["Invalid"]<<endl;
return 0;
}
题解:一开始想着删除对应字符,后面想到只需要不输出最少的字符就行
#include
using namespace std;
bool cmp_value(const pair<char, int> left,const pair<char,int> right)
{
return left.second < right.second;
}
int main(){
string s,res;
getline(cin,s);
int len=s.size();
unordered_map<char,int> hash;
for(int i=0;i<len;i++){
hash[s[i]]++;
}
auto j=min_element(hash.begin(),hash.end(),cmp_value);
for(int i=0;i<len;i++){
if(hash[s[i]] > j->second)
res+=s[i];
}
cout<<res<<endl;
return 0;
}
#include
#include
#include
using namespace std;
int main(){
set<char>hash;
string s;
getline(cin,s);
int len=s.size();
for(int i=0;i<len;i++){
if(hash.find(s[i])==hash.end()){
hash.insert(s[i]);
}
}
cout<<hash.size()<<endl;
}
题解: 注意遍历输出hash的手法,注意map输出时会按照key的值进行排序,unordered_map不会,而且是随机的。
#include
#include
using namespace std;
int main(){
int n,index,value;
map<int,int>hash;
cin>>n;
for(int i=1;i<=n;i++){
cin>>index>>value;
hash[index]+=value;
}
for(auto it=hash.begin();it!=hash.end();it++){
int front = it->first; //key
int end = it->second; //value
cout<<front<<' '<<end<<endl;
}
return 0;
}
题解: 注意hash的语法
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
unordered_map<int,int> hash_table;
int i=0,len=nums.size();
for(i=0;i<len;i++){
auto it=hash_table.find(target-nums[i]);
if(it!=hash_table.end()){
return{i,it->second};
}
hash_table[nums[i]]=i;
}
return {};
}
};
题解1: 题解中有用unordered_set的,看看和map有什么不同
class Solution {
public:
int findRepeatNumber(vector<int>& nums) {
int i=0,len=nums.size();
unordered_map<int,int> hashtable;
for(i=0;i<len;i++){
auto it=hashtable.find(nums[i]);
if(it!=hashtable.end()){
return nums[i];
}
hashtable[nums[i]]=i;
}
return -1;
}
};
题解2: 通过hash表记录每个数组项出现的次数
class Solution {
public:
int findRepeatNumber(vector<int>& nums) {
int i=0,len=nums.size();
unordered_map<int,int> hashtable;
for(i=0;i<len;i++){
hashtable[nums[i]]++;
if(hashtable[nums[i]]==2)
return nums[i];
}
return -1;
}
};
题解: 原题是超过一半,这样可以直接排序取中值,现在是超过三分之一,可以用哈希记录每个元素出现的次数,注意输入输出的写法
#include
#include
#include
#include
#include
using namespace std;
class solution {
public:
int myfun(vector<int>& nums) {
unordered_map<int, int> hash;
int res = 0, len = nums.size();
for (int i = 0; i < len; i++) {
hash[nums[i]]++;//把hash表想象成一个数组,hash[nums[i]]的初始值为0
if (hash[nums[i]] >= len / 3)
return nums[i];
}
return -1;
}
}mysolution;
void main(){
vector<int> mynums;
int a;
while (cin >> a) {
mynums.push_back(a);
}
vector<int>& nums= mynums;
int ans= mysolution.myfun(nums);
cout << ans << endl;
}
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
unordered_map<ListNode *,int>hash;
ListNode *p1=headA,*p2=headB;
while(p1||p2){
hash[p1]++;
hash[p2]++;
if(p1&&hash[p1]==2){//注意这里的p1&&,排除hash[nullptr]的计数
return p1;
}
if(p2&&hash[p2]==2){//注意这里的p2&&,排除hash[nullptr]的计数
return p2;
}
if(p1)
p1=p1->next;
if(p2)
p2=p2->next;
}
return nullptr;
}
};
题解:注意链表的声明,注意链表的创建,注意如何获取多组输入
#include
using namespace std;
struct ListNode{//注意这里链表定义的手法
int m_nKey;
ListNode* m_pNext;
ListNode() : m_nKey(0), m_pNext(nullptr) {}
ListNode(int x) : m_nKey(x), m_pNext(nullptr) {}
ListNode(int x, ListNode *next) : m_nKey(x), m_pNext(next) {}
};
int main(){
struct ListNode * dummy=new(struct ListNode);
struct ListNode * cur=dummy;
int n,a,k;
vector<int>v;
while(cin>>n){//注意这里循环获取多组输入的手法
for(int i=0;i<n;i++){
cin>>a;
v.emplace_back(a);
}
cin>>k;
int len=v.size();
for(int i=0;i<len;i++){//注意这里创建链表的手法
cur->m_pNext=new(struct ListNode);
cur=cur->m_pNext;
cur->m_nKey=v[i];
}
cur=dummy;
struct ListNode *slow=cur,*fast=cur;
for(int i=0;i<k;i++)
fast=fast->m_pNext;
while(fast){
slow=slow->m_pNext;
fast=fast->m_pNext;
}
cout<<slow->m_nKey<<endl;
}
}
题解: 双指针,往中间靠,谁小谁移动
class Solution {
public:
int maxArea(vector<int>& height) {
int cur_area=0,max_area=0,len=height.size();
int head=0,tail=len-1;
while(head!=tail){
if(height[head]<height[tail]){
cur_area=height[head]*(tail-head);
max_area=max(max_area,cur_area);
head++;
}
else{
cur_area=height[tail]*(tail-head);
max_area=max(max_area,cur_area);
tail--;
}
}
return max_area;
}
};
题解: 排序,优化版三重for循环,注意for循环中continue和break的用法区别
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
int n = nums.size();
sort(nums.begin(), nums.end());
vector<vector<int>> ans;
// 枚举 a
for (int first = 0; first < n; ++first) {
// 需要和上一次枚举的数不相同
if (first > 0 && nums[first] == nums[first - 1]) {
continue;
}
// c 对应的指针初始指向数组的最右端
int third = n - 1;
int target = -nums[first];
// 枚举 b
for (int second = first + 1; second < n; ++second) {
// 需要和上一次枚举的数不相同
if (second > first + 1 && nums[second] == nums[second - 1]) {
continue;
}
// 需要保证 b 的指针在 c 的指针的左侧
while (second < third && nums[second] + nums[third] > target) {
--third;
}
// 如果指针重合,随着 b 后续的增加
// 就不会有满足 a+b+c=0 并且 b
if (second == third) {
break;
}
if (nums[second] + nums[third] == target) {
ans.push_back({nums[first], nums[second], nums[third]});
}
}
}
return ans;
}
};
题解: 双指针,交换
class Solution {
public:
vector<int> exchange(vector<int>& nums) {
if(nums.size()==0)
return nums;
int i=0,len=nums.size();
int head=0,tail=len-1;
int swap=0;
while(head!=tail){
if(nums[tail]%2==0){
tail--;
}
else{
swap=nums[head];
nums[head]=nums[tail];
nums[tail]=swap;
head++;
}
}
return nums;
}
};
class Solution {
public:
char firstUniqChar(string s) {
vector<int> m(26,0);
int i=0,len=s.size();
for(i=0;i<len;i++){
m[s[i]-'a']++;
}
for(i=0;i<26;i++){
if(m[i]==1)
return (char)('a'+i);
}
return ' ';
}
};
题解: 两个跑速不同的人如何相遇,答,不断交换跑道,注意这里就算没有交点,也会同时等于nullptr
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
if (headA == nullptr || headB == nullptr) {
return nullptr;
}
ListNode *pA = headA, *pB = headB;
while (pA != pB) {
pA = pA == nullptr ? headB : pA->next;
pB = pB == nullptr ? headA : pB->next;
}
return pA;
}
};
#include
using namespace std;
int main(){
float x;
cin >> x;
cout << (int)(x+0.5) << endl; //强制类型转换,默认向下取整
return 0;
}
#include
using namespace std;
int main(){
long n;
cin >> n;
for(long i = 2; i <= sqrt(n) && i <= n; i++){ //从小到大的质因子,质因子不会超过它的开方
while(n % i == 0){ //所有的质数前面全部除掉,后续就不会有合因子
cout << i << " ";
n /= i; //除掉质因子
}
}
if(n - 1) //自己本身就是质数
cout << n << " ";
return 0;
}
#include
#include
using namespace std;
int main(){
int n,cnt=0;
while(cin>>n){
while(n){
n=n&(n<<1);
cnt++;
}
cout<<cnt<<endl;
cnt=0;
}
return 0;
}
题解1:
class Solution {
public:
int hammingWeight(uint32_t n) {
int cnt=0;
for(int i=0;i<32;i++){
if((n&1)==1){
cnt++;
}
n=n>>1;
}
return cnt;
}
};
题解2: 书上的简便方法
int hammingWeight(uint32_t n) {
int cnt=0;
while(n)
{
n=n&(n-1);
cnt++;
}
return cnt;
}