leetcode 234. 回文链表 C++

解法有两种最基本的方式,空间复杂度O(n)–递归方式,空间复杂度O(1)–找中点、反序后半部分链表、比较即可。

1 递归方式

最核心基础的数据类型是数组,链表。进而组成栈、队、堆、树、图等。
从链表定义来看就注定它具有递归的特点,递归是浓墨重彩的一部分。

void traverse(ListNode *head){
    //前序遍历代码--正序
    traverse(head->next);
    //后序遍历代码--倒序
}

其实递归的学习方法就是手动画下递归树,很显然,代码的相对顺序直接决定遍历方式。
下面就是一个简单的实现方式,这里分析下‘注意"
‘注意: "递归代码不能从表面去看,如注意2,其实这里整个链表已经全部全部入栈,也就是倒序了,一定要结合递归树
之后myLeft只是配合同时移动一步而已。
最后,代码空间复杂度是O(n),结果排在后,用的是系统栈,这里存放的指针,所以数据量大也不会很快爆栈。

/** \brief      isPalindrome  回文链表
 *  \author     xxx
 *  \copyright  GNU Public License
 *  \version    1.0 
 *  \date       2020-1-14
 *  \remark     递归方式求解--后序遍历也就是倒序
 * 
 *  \param[in] head 输入链表
 *  \return         返回是否是回文链表
 */
ListNode *myLeft = NULL;                    /**<left和库名重复,所有取了新名字 */
bool traverse(ListNode *right){
    if(right == NULL)    return true;        /**<相当于初始条件,假定初始为真 */
    bool res = traverse(right->next);       /**<------注意1-----*/

    res = (res && right->val == myLeft->val);/**<------注意2-----*/
    myLeft = myLeft->next;                  /**<右移动一个即可 */
    return res; 
}

bool isPalindrome(ListNode* head) {
    myLeft = head;                          /**<左边指针往右走 */
    return traverse(head);
}

2 找中点、反序后半部分链表、比较即可

1 找中点
很简单,相同的路程,一个速度是另外一个的两倍,快的到终点,慢的就在中间;
如果是偶数个,就在中间偏右的位置;
循环的判断条件?你画一个3个长度,4个长度走一遍就知道了哈(奇偶各有一个判断条件);
2 反序后半部分链表
反转的时候需不需要考虑奇数还是偶数,其实不需要,即使是奇数个,反转变成最后一个啊,
换句话说,前面的长度肯定是小于等于后面,若后面的多一个,其实是回文串中间的位置,不用考虑
3 比较即可
由于前面的长度肯定是小于等于后面,所以遍历前面的即可

/** \brief      isPalindrome  回文链表
 *  \author     wzk
 *  \copyright  GNU Public License
 *  \version    1.0 
 *  \date       2020-1-13
 * 
 *  \param[in] head 输入链表
 *  \return         返回是否是回文链表
 */
bool isPalindrome(ListNode* head) {
    /**<STEP1 寻找链表的中点,若为奇数则是中间偏右(slow) */
    /**<fast指针每次走两步,slow每次走一步 */
    ListNode *fast = head;
    ListNode *slow = head;
    while (fast != NULL && fast->next != NULL) {    /**<手动画下元素只有3,4的情况*/
        fast = fast->next->next;
        slow = slow->next;
    }

    /**<STEP2 后半部分反转 */
    ListNode *secondHalfHead = NULL;
    while (slow != NULL) {
        ListNode *temp = slow->next;            /**<这里要临时转存下p->next,最后又恢复给p  */

        slow->next = secondHalfHead;
        secondHalfHead = slow;

        slow = temp;
    }

    /**<STEP3 比较,如果是奇数,由于slow取得中间偏右,回文中间那个不会考虑哦 */
    ListNode *p = head;
    ListNode *q = secondHalfHead;
    while (p != NULL) {
        if(p->val != q->val)
            return false;
        p = p->next;
        q = q->next;
    }

    return true;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值