您的位置:首页 > 其它

支线任务1

2015-10-14 22:07 267 查看
Problem:Given a singly linked list, determine if it is a palindrome.

问题分析:

  题目很简单,比较字符串是否为回文。思路就是依次比较对称位置上的数对是否相等。数据结构为单链表:

struct ListNode {
int val;
ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};


算法比较:

  方法一:首先想到的是最无趣的办法。指针p从前向后遍历,直到中间节点,p每后移一位,q就从头结点开始移到与p相对称的位置,进行比较。

  方法二:稍稍优化一下,将链表的尾结点的next指针指向链表的中间节点,即链表的后半部分成为一个循环链表,这样,指针p从前向后遍历,直到中间节点,p每后移一位,q就从当前位置后移1/2n-1(假设n为偶数,奇数的情况类似),进行比较。

  以上两个方法的时间复杂度O(n2),原因在于单链表难以找到上一节点。那么能否只将链表从前往后遍历一遍就可以比较了呢?

  方法三:由于顺序表很容易找到上一节点,很显然可以找到中间节点,指针p从第一个节点开始,遍历前一半时,将数据导出为一个顺序表,然后遍历后一半,一一比较。(也可将其想成一个栈,遍历前一半的时候一一压栈,遍历后一半时,如果当前位置和栈顶元素相同,出栈,否则,返回false)

  代码如下:

int getLength(ListNode* head){
ListNode* p = head;
int length = 0;
while (p) {
p = p->next;
length++;
}
return length;
}
class Solution {
public:
bool isPalindrome(ListNode* head) {
//寻找中间节点
int l = getLength(head);
int n = l % 2 ? ( l + 1 ) / 2 : ( l / 2 + 1 );
//构造栈s,给其赋值
int* s = new int
;
ListNode* p = head;
for (int i = 0; i < n - 1; i++, p = p->next) {
s[i] = p->val;
}
//m是栈顶元素的下标,p指向和栈顶元素对称的节点
p = l % 2 ? p->next : p;
int m = n - 2;
while (p && ( m >= 0 ) ) {
//如果栈顶元素和当前节点p的值不一样,返回false
if(s[m] != p->val) return false;
//否则弹出栈顶元素,p后移一位
m--;
p = p->next;
}
return true;
}
};


  但是这种做法的缺点在于空间复杂度为O(n)。

算法优化:

可以将前二分之一的链表反转,这样做的时间复杂度为O(n)且空间的复杂度为O(1)。

计算链表长度和寻找中间节点可以合并。即指针p后移一步时,指针q后移两步,这样当q到达尾结点时,p即为中间节点。链表的长度也能在此过程中得到。

  然而以上两点洒家并木有想到:-( ,具体思路和代码可移步此处
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: