LeetCode刷题笔记(九)--- Hash、链表、回文

文章内容为LeetCode刷题笔记,如发现错误请多多指教

26、回文字符串:hash思想

给定一个仅由小写字母组成的字符串。现在请找出一个位置,删掉那个字母之后,字符串变成回文。请放心总会有一 个合法的解。如果给定的字符串已经是一个回文串,那么输出-1。
在这里插入图片描述
我们可以从头部和尾部进行字符比较,因为如果是回文字符串的话,头尾是相同的,如果遇到不同的,我们要找的值不是头指针指向的这个值就是尾指针指向的值,只需要在验证下就可以了

#include<iostream>
#include<string>
using namespace std;

bool isPalindrome(string &s,int *start,int *end){
    int i=0;
    int j=s.size()-1;
    bool result = true;
    while(i<=j){
        if(s[i]==s[j]){
            j--;i++;
        }
        else{
            result=false;
            break;
        }
    }
    if(start!=nullptr) *start=i;
    if(end!=nullptr) *end=j;
    return result;
}
int main(){
    int num=0;
    cin>>num;
    while(num){
        string s;
        cin>>s;
        int start =0;
        int end=s.size()-1;
        if(isPalindrome(s, &start, &end)){
            cout<<-1<<endl;
        }
        else{
        //erase(pos,n); 删除从pos开始的n个字符,比如erase(end,1)就是从end开始删除第一个字符(即end)
            s.erase(end, 1);
            if(isPalindrome(s, nullptr, nullptr)){
                cout<<end<<endl;
            }
            else{
                cout<<start<<endl;
            }
        }
        num--;
    }
}

27、把数组排成最小的数:排序算法的特殊理解

输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中小的一个。例如输入数 组{3,32,321},则打印出这三个数字能排成的小数字为321323。
在这里插入图片描述

我们把说法换一下,对于本题,我们要的有效序列是:序列中任何一个元素y,和它前的任何一个元素x进行有序组合形成 xy,比和他后面的任何一个元素z进行有效序列组合yz,满足条件xy < yz(采用字典序列排序) ,如{32,31},有效组合是3132,所以我们拍完序列之后序列变成{31, 32}

class Solution {
public:
    static bool cmp(int x,int y){
        //要保证找到x,y构成的序列中,让小的放在前面 
        string nx=to_string(x);
        string ny=to_string(y);
        string A=nx+ny;
        string B=ny+nx;
        return A<B;
    }
    string minNumber(vector<int>& nums) {
        if(nums.size()==0){
            return " ";
        }
        //这个排序会根据我们写的cmp方法进行排序,即按小序列升序
        sort(nums.begin(),nums.end(), cmp);
        string result;
        for(int i=0;i<nums.size();i++){
            result+=to_string(nums[i]);
        }
        return result;
    }
};

28、两个链表的第一个公共节点:单链表理解,临界条件判定

输入两个链表,找出它们的第一个公共节点。

如下面的两个链表:
在这里插入图片描述
在节点 c1 开始相交。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

针对这个题,我们可以进行以下思路:
1、首先判断两个链表是否相交,怎么样才算相交呢,必须最后一个节点是相同的才可以,因为相交的话最后一个节点一定是相同的
2、如果相交,怎么找出相交节点呢,那么需要遍历两个链表的节点,并进行节点比较,第一个相同的节点就是我们要找的
3、但是链表长度不一样,比较的话要怎么办呢,我们可以先让长的链表指针走几步,然后再开始一起比较
整理好思路,代码如下:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    //该方法用来返回链表最后一个节点指针,并且length是一个输出型参数
    ListNode *getlistLength(ListNode *head,int &length){
        if(head==nullptr){
            return head;
        }
        ListNode *end=head;
        while(head){
            end=head;
            head=head->next;
            length++;
        }
        return end;
    }
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        //当两个头指针有一个为空的时候,就可以不跟它玩了
        if(headA==nullptr||headB==nullptr){
            return nullptr;
        }
        int lengthA=0,lengthB=0;
        ListNode *endA=getlistLength(headA,lengthA);
        ListNode *endB=getlistLength(headB,lengthB);
        //先判断最后节点是否相同,因为如果相交的话,最后一个节点一定是一样的
        if(endA!=endB){
            return nullptr;
        }
        //判断两个链表长度,长的一个先走长度差步,然后在一起比对每个节点是否相同
        if(lengthA>lengthB){
            int step=lengthA-lengthB;
            while(step){
                headA=headA->next;
                step--;
            }
            while(lengthB){
                //如果遍历到相同的节点了,那么直接返回该节点即可,两个节点任选其一返回
                if(headA==headB){
                    return headA;
                    //break;
                }
                //如果不相同,那么继续往后走
                else{
                    headA=headA->next;
                    headB=headB->next;
                }
            }
        }
        else{
                int step=lengthB-lengthA;
                while(step){
                    headB=headB->next;
                    step--;
                }
                while(lengthA){
                    if(headB==headA){
                        return headB;
                        //break;
                    }
                    else{
                        headA=headA->next;
                        headB=headB->next;
                    }
                }
            }
        //到达这里说明没有节点是相同的,返回空指针
        return nullptr;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值