数据结构和算法之链表

Scroll Down

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

示例 1:

输入: 1->2
输出: false
示例 2:

输入: 1->2->2->1
输出: true
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
    /** 果不其然的超时间了,
    */
	public boolean isPalindrome(ListNode head) {
        ListNode self=head;
        ListNode reversalNode=reversal(head);
        while(self!=null&&reversalNode!=null){
            if(self.val!=reversalNode.val){
                return false;
            }
        }
        return true;

    }
    public ListNode reversal(ListNode head){
        ListNode a=head,b=null;
        while(a!=null){
            //记录a的后继节点
           ListNode c=a.next;
            //解绑a节点
            a.next=b;
            //在b指针绑定上解绑带来的a节点
            b=a;
            //把曾经记下的a的后继节点,还给a,用于下次的迭代。
            a=c;
        }
        return b;
    }

改进版本,翻转一半进行比较 使用快慢指针
 public boolean isPalindrome(ListNode head) {
        if(head==null){
            return true;
        }
        ListNode self=head;
        ListNode reversalNode=reversal(getTailNode(head));
        while(self!=null&&reversalNode!=null){
            if(self.val!=reversalNode.val){
                return false;
            }
            self=self.next;
            reversalNode=reversalNode.next;
        }
        return true;

    }
    public ListNode reversal(ListNode head){
        ListNode a=head,b=null;
        while(a!=null){
            //记录a的后继节点
           ListNode c=a.next;
            //解绑a节点
            a.next=b;
            //在b指针绑定上解绑带来的a节点
            b=a;
            //把曾经记下的a的后继节点,还给a,用于下次的迭代。
            a=c;
        }
        return b;
    }
    public ListNode getTailNode(ListNode head){
        ListNode fast=head,slow=head;
       while (fast.next != null && fast.next.next != null) {
            fast = fast.next.next;
            slow = slow.next;
        }
        return slow;
    }


 /**
   *还可以遍历链表,然后把数据放在数组中,然后使用首尾双指针比对
   */
 public boolean isPalindrome(ListNode s) {
        if (s == null) return true;
        ListNode head=s,head1=s;
        int leng=0;
        while(head!=null){
            leng++;
            head=head.next;
        }
        int i=0,j=0;
        int[] a=new int[leng];
        while(head1!=null){
            a[i++]=head1.val;
            head1=head1.next;
        }
        int k=i-1;
        while (j<k){
            if (a[j]!=a[k]){
                return false;
            }
            j++;
            k--;
        }
        return true;

    }

反转一个单链表。

示例:

输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL
/**
* Definition for singly-linked list.
* public class ListNode {
*     int val;
*     ListNode next;
*     ListNode(int x) { val = x; }
* }
*/
/**
     *反转列表,1->2->3->4->5  -》 5->4->3->2->1
     *首先我需要去遍历当前的链表,采取迭代法
     * 利用c记录头节点的后缀,b作为结果,用a去进行迭代。通过交换a的值,最终当遍历完毕,
     * b就是反转后的列表
     */
   public ListNode reverseList(ListNode head) {
       ListNode a=head,b=null,c;
       while(a!=null){
           c= a.next;
           a.next=b;
           b=a;
           a=c;
       }
       return b;
   }

给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点。

示例:

给定一个链表: 1->2->3->4->5, 和 n = 2.

当删除了倒数第二个节点后,链表变为 1->2->3->5.
/**
     * 采取快慢指针来迭代删除。
     * 参照两数相加的链表操作,使用辅助链表(哨兵)
     * 根据题意我们知道要删除倒数第N个,所以快慢指针的初始步长差就是N,由于使用辅助列表所以相差为N+1;
     * 直到快指针走完,那么删除慢指针的下一个就是删除了倒数第N个。
     * @param head
     * @param n
     * @return
     */

    public ListNode removeNthFromEnd(ListNode head, int n) {
        ListNode result=new ListNode(0);
        result.next=head;
        ListNode start=result;
        ListNode end=result;
        int i=0;
        //直到N指针走完了
        while(start!=null){
            if(i<n+1){
                i++;
                //计算N指针
                start=start.next;
            }else{
                start=start.next;
                end=end.next;
            }
        }
        //删除这个下一个节点
        end.next=end.next.next;
        //返回原链
        return result.next;

    }

将两个有序链表合并为一个新的有序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 

示例:

输入:1->2->4, 1->3->4
输出:1->1->2->3->4->4
/**
     * 合并俩个有序链表
     * 输入:1->2->4, 1->3->4
     * 输出:1->1->2->3->4->4
     * 参照归并排序的算法。
     * 当 l1,l2不为空的时候,遍历全部,
     * 如果l1遍历完了那么直接把l2的后续部分添加在结果后面。同理l2走完了 l1也是一样加载结果后面
     * 关键在于比较l2和l1节点的值
     * l1.val>=l2.val
     *      :更新结果为l2节点,同时把l2=l2.next。然后更新结果r=r.next;
     * l1.val<l2.val
     *      :更新结果为l1节点,同时把l1=l1.next。然后更新结果r=r.next;
     * 遍历全部完毕之后,输出原始指针的后继。即新链表
     * @param l1
     * @param l2
     * @return
     */

    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        ListNode r=new ListNode(0);
        ListNode ret=r;
        while(l1!=null||l2!=null){
            if(l1==null){
                ListNode x=l2.next;
                l2.next=null;
                r.next=l2;
                l2=x;
            }else if(l2==null){
                ListNode x=l1.next;
                l1.next=null;
                r.next=l1;
                l1=x;
            }else if(l1.val>=l2.val){
                ListNode x=l2.next;
                l2.next=null;
                r.next=l2;
                l2=x;
            }else{
                ListNode x=l1.next;
                l1.next=null;
                r.next=l1;
                l1=x;
            }
            r=r.next;
        }
        return ret.next;

    }