作业感受
题目地址:https://leetcode-cn.com/leetbook/read/linked-list/fov6t/
其实这道题对我来说有些难的感觉,因为一开始就想着回文链表必须是偶数个,结果提交以后发现有错,回头才测试[1]这个用例,结果是true啊,血的教训啊,呜呜呜~~~
于是开始考虑奇数个元素和偶数个元素两种情况。
我的思路是这样的:
1)先遍历链表的所有元素,拿到元素的个数;
2)如果是偶数,快速判断2个元素的特殊情况,然后采取反转前半段链表,再逐一对比前一半和后一半的元素是否逐一相等,如果是返回true,否则返回false;
3)如果是奇数,快速判断3个元素的特殊情况,然后采取反转前半段链表,再逐一对比前一半和后一半的元素是否逐一相等,如果是返回true,否则返回false.
这么想之后,提交了两次,却还是有问题。然而在leetcode上面也不方便debug,于是我决定查找官方题解。
官方给出了两种方法,1)将链表改为数组,然后用下标遍历比较;
2)用递归算法迭代比较。
看了官方给的代码,Java的代码果然还是更冗长啊,不过还是想要把java重新学一下,正好结合设计模式的内容一起。不把双手插进土地,怎么能种植自己的庄稼呢?
看了官方的代码,其实觉得有一个地方有疑问,就是在使用List的时候觉得还是有些不谨慎,题目给了val的区间是【1,9】,但是也没有说都是整数啊,这个结构可能会出现问题吧,内心有一丝不安,我的话就用arrayList好啦。
反省一下自己,明明感觉到链表前后退很不方便,也没有考虑改变数据结构,思维还是有些僵化了。恩,继续努力。感觉多年不写代码还是自己太懒的缘故,不能简单归咎到工作性质。感谢leetcode这个平台,给了我这么多好的练习题。终于又找回上学时的探索乐趣啦。
也记录一下错题的代码,真的是思路很纠结啦。
错题代码
class Solution {
public boolean isPalindrome(ListNode head) {
if( head == null ) return false;
if( head.next == null) return true;
ListNode fast = head, slow, middle;
int count = 0,sz =0;
while(fast != null){
sz++;
fast = fast.next;
}
// 如果链表长度为偶数
if(sz%2 == 0){
fast = head;
if(sz == 2){
if(fast.val == fast.next.val) return true;
else return false;
}
// fast找到链表的中点右边的节点
while(count != sz/2){
count++;
fast = fast.next;
}
middle = fast;
slow = head;
fast = head;
//反转前半部分链表
while(fast != middle && slow.next != middle){
fast = fast.next;
slow.next = fast.next;
head.next = new ListNode(fast.val, head);
}
// 对比反转后的前半部分链表和后半部分是否逐一相等,是则返回true,否则返回false
slow = head;
fast = middle;
while(slow.val == fast.val){
slow = slow.next;
fast = fast.next;
if(slow.val != fast.val) return false;
if(fast == null) return true;
}
}else{
fast = head;
if(sz == 3){
if(fast.val == fast.next.next.val) return true;
else return false;
}
//fast找到链表的中点
while(count != (sz-1)/2){
count++;
fast = fast.next;
}
middle = fast;
slow = head;
fast = head;
//反转前半部分链表
while( slow.next != middle && fast != middle){
fast = fast.next;
if(fast == middle) break;
slow.next = fast.next;
head.next = new ListNode(fast.val, head);
}
// 对比反转后的前半部分链表和后半部分是否逐一相等,是则返回true,否则返回false
slow = head;
fast = middle.next;
while(slow.val == fast.val && fast != null){
slow = slow.next;
fast = fast.next;
if(slow.val != fast.val) return false;
if(fast == null) return true;
}
}
return false;
}
}
改错代码
很认可官方给出的第一种思路,就采用啦。第二中递归的思路我觉得理解起来有些困难,这个涉及到递归的逆序打印问题,目前我的状态还不是很适合这种递归,我决定只跟一种官方思路啦。
class Solution {
public boolean isPalindrome(ListNode head) {
if(head == null) return false;
List vals = new ArrayList();
ListNode curr = head;
for(int i = 0; curr != null; i++){
vals.add( curr.val );
curr = curr.next;
}
int n = vals.size();
int front=0, back = n-1;
while(front < back){
if(!vals.get(front).equals(vals.get(back))) return false;
front++;
back--;
}
return true;
}
}
改错代码表现
总体表现很差啊。
不过我发现这个统计结果也不稳定,上一次我把同样的代码在不同时间提交了,结果差了1ms, 但是那道题原来就是0ms,大家都是0ms,结果虽然差了1ms,但是百分比是相差100%的。理论和实践的距离啊,总是那么扑朔迷离~~