leetcode学习记录_回文

9. 回文数

给你一个整数 x ,如果 x 是一个回文整数,返回 true ;否则,返回 false 。

回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。例如,121 是回文,而 123 不是。

示例 1:
输入:x = 121
输出:true
来源:力扣(LeetCode)

进阶:你能不将整数转为字符串来解决这个问题吗?

看见题目的第一眼就是转成字符串或者数组,然后刷刷的的写了字符串的,发现,速度和内存使用排名都特别低,有点纳闷,看了题解才想到,如果数字是回文数,那么它反转的数字也等于原数字,而且 我们甚至不需要全部反转,只需要反转一半就行了
在这里插入图片描述
这题需要注意三点

一:
数字后缀为0 ,10 , 100 , 110这种,最后x = 0,rx = 1,虽然不直接相等,但是rx/10 = 0了。满足这个条件,显然这不是我们想要的结果,因此必须提前剔除掉
当然还有负数也是不可能为回文的,0本身的话是没问题的

二:
数字长度为奇数,这种情况就 if ( x == rx/10 )
三:
数字长度为偶数, if ( x == rx )

class Solution {
public:
    bool isPalindrome(int x) {
    //排除特殊情况1
		if(x < 0 || (x!=0 && x%10 == 0)) return false;
		int rx = 0;
		while(rx < x)//只需要反转一半
		{//反转并缩减x
			rx = rx*10 + x%10;
			x /= 10;
		}
		return rx == x || rx/10 == x;//判断奇偶数两种情况
    }
};


5. 最长回文子串

给你一个字符串 s,找到 s 中最长的回文子串。

示例 1:

输入:s = “babad”
输出:“bab”
解释:“aba” 同样是符合题意的答案。
来源:力扣(LeetCode)

思路:
中心扩展,
从左往右遍历字符串,把每个字符串以及每对相邻字符串都当成回文字符串的中心
在这里插入图片描述
然后用子程序求出每个中心的回文长度,然后维护一个最大长度maxlen,再维护两个指针start , end ,每次maxlen更新最大值时,就接着更新两指针的位置

最后,遍历完以后,以start为依据,maxlen为长度,提取子字符串返回

求长度子程序的思路:
我们传入字符串的引用和中心,中心用两个变量(left , right)确定,如果是要求奇数长度,就left = right , 偶数长度就 right = left + 1
然后依次比较中心两端的字符,如果相等就扩展,继续比较,不相等或者两端到达了原字符串的边界,就返回长度,
这里要注意一下:字符串下标越界的可能性
所以我们利用&&的短路特性,把边界条件写前面,匹配条件写后边,这样如果到达边界就会直接返回,不会再去对中心两端的字符串做匹配,也就不会越界

第二点:
left 和 right 扩展到最后,其实是在回文子字符串的外边的,不是指向字符串两端,所以回文子字符串长度不是 right - left + 1 ,而是 right - left - 1

代码:

class Solution {
public:
    int count (const string& s , int left , int right)
    {//利用&&得短路特性防止越界并简化代码
        while(left >= 0 && right <s.size() && s[left] == s[right])
        {
            left--;//扩展
            right++;
        }
        return right-left-1;//返回正确的长度
    }
    string longestPalindrome(string s) {
        int N = s.size();
        if(N == 0 || N == 1) return s;//
        int maxlen = 0, start = 0, end = 0;
        for(int i = 0;i<N;++i)
        {
            int len1 = count(s,i,i);//奇数中心
            int len2 = count(s,i,i+1);//偶数中心
            //维护最大回文子字符串长度
            maxlen = max(max(len1,len2),maxlen);
//这里就是维护start  和  end            
            if(maxlen > end - start + 1)
            {
                end = i + maxlen /2;
                start = end - maxlen + 1;
            }
        }
        return s.substr(start,maxlen);
    }
};



234. 回文链表

请判断一个链表是否为回文链表。

示例 :
输入: 1->2
输出: false
进阶:
你能否用 O(n) 时间复杂度和 O(1) 空间复杂度解决此题?
如果不要求空间复杂度的话,直接转成数组就很快,既然有要求,就只能沿用文章第一题的思路了,一个回文,分成两半,一半的翻转肯定等于另一半

**思路:**找中点的同时求链表长度,然后从中点把后半部分翻转,再与前半部分比较,如果有不相等的就说明不是回文

这里注意一下,我们已经算出了链表长度,所以不管链表长度是奇数还是偶数,只要对两个子链表进行 size/2 次比较即可

代码:

class Solution {
    ListNode* reverse(ListNode*start)
    {
        ListNode*cur = start, *pre = nullptr;//翻转链表的程序
        while(cur)
        {
            ListNode*next = cur->next;
            cur->next = pre;
            pre = cur;
            cur = next;
        }
        return pre;
    }
public:
    bool isPalindrome(ListNode* head) {
        int size = 0;
        ListNode* head1 = head, *mid = head;
        while(head1)
        {//找到中点并求长度,如果是两个中点,就定位到右边
            head1 = head1->next;++size;
            if(!head1) break;
            head1 = head1->next;++size;
            mid = mid->next;
        }
        head1 = head;
        ListNode*head2 = reverse(mid);
        for(int i = 0;i<size/2;++i)
        {//将两个子链表比较size/2次
            if(head1->val != head2->val) return false;//一旦发现不一样的就说明不是回文
            head1 = head1->next;head2 = head2->next;
        }
        return true;
    }
};


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

timathy33

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值