LeetCode刷题:链表

LeetCode刷题:链表

  • 237. 删除链表中的节点
  • 19. 删除链表的倒数第N个节点
  • 141.环形列表
    • 方法一:HashSet
    • 方法二:快慢指针【待写】
  • 234. 回文链表
    • 方法二:快慢指针【待写】
  • ⚠️ 206. 反转链表
  • 21. 合并两个有序链表

237. 删除链表中的节点

这道题目比较奇葩,因为一般来说都是传一个head进来,但是这里直接传了要删除的元素进来。以删除[4,5,1,9]中的5这个node为例子。

  • 一般情况
1
4
5
9

第一步:

1
4
5
9

第二步:

1
4
5
9

第三步:

1
4
9
  • 这道题目的情况
    因为知道5这个node:
1
4
5
9

第一步:先复制一个next元素的值

1
4
9
1

第二步:把next元素删掉

1
4
9
  • 具体实现:
public void deleteNode(ListNode node) {
     node.val=node.next.val; //因为不会删除末尾节点,所以node.next不会为null
     node.next=node.next.next; //因为不会删除末尾节点,所以node.next不会为null
}

19. 删除链表的倒数第N个节点

  • 方法一:快慢指针。
public ListNode removeNthFromEnd(ListNode head, int n) {
        ListNode l=head;
        ListNode r=l;
        // 因为n保证是有效的,所以从头开始一定不会越界
        for(int i=0;i<n;i++){
            r=r.next;
        }
        //如果要删除的是头元素
        if(r==null)
            return head.next;
        while(r.next!=null){
            l=l.next;
            r=r.next;
        }
        l.next=l.next.next;
        return head;
}

141.环形列表

  • 收获:
    • HashSet: 其实就是一个集合,不允许存在两个同样的值。
    import java.util.HashSet;
    import java.util.Set;
    Set<ListNode> m = new HashSet<>();
    m.contains(tmp) //如果集合里面有tmp,tmp的类型是ListNode,这里用了泛型
    m.add(tmp);  //
    
    • 快慢指针
  • 记号:
    • 给一个list和pos,pos表示最后一个Node的指针指向的元素。如果 p o s = − 1 pos=-1 pos=1,则表示尾指针指向null
    • 例子:
      head = [3,2,0,-4], pos = 1
    0
    2
    3
    -4

方法一:HashSet

每次往里面添加ListNode地址,若重复,则输出true(有环)

public boolean hasCycle(ListNode head) {
		ListNode tmp=head;
		//如果为空的情况
		if (head==null)
            return false;
		// 如果只有一个元素的情况,其实可以去掉,因为一个元素应该没有办法成环。
		if (head.next == null)
			return false;
		Set<ListNode> m = new HashSet<>();
		while(tmp.next!=null) {
			if(!m.contains(tmp)) {
				m.add(tmp);
			}
			else
				return true;
            tmp=tmp.next;
		}
		return false;
}

方法二:快慢指针【待写】

一个一次移动1格,一个一次移动2格,如果相遇,则存在环形结构。

234. 回文链表

  • 收获:
    • ⚠️ 对于ArrayList 里面的元素相等判断应该用.equal而非==
    • ⚠️ 快慢指针法(快指针每次移动2格,慢指针每次移动1格)
      • 别人的一张图片,当列表为奇数个的时候,fast.next==null。当列表为偶数个的时候,fast==null。具体程序里面,应该把fast==null放在前面。LeetCode刷题:链表_第1张图片
  • 方法一:全部提取出来,然后套用链表判断。
    O(n) 时间复杂度和 O(n) 空间复杂度
public ArrayList<Integer> subtract(ListNode head){
		ArrayList<Integer> l = new ArrayList<>();
        while(head!=null){
        	l.add(head.val);
        	head = head.next;
        }
        return l;
    }
    public boolean isPalindrome(ListNode head) {
        ArrayList<Integer> l = subtract(head);
        int i=0,j=l.size()-1;
        while(i<j) {
        	if(!l.get(i).equals(l.get(j))){
        		return false;
            }
            i++;
            j--;
        }
        return true;
    }

方法二:快慢指针【待写】

⚠️ 206. 反转链表

目的:翻转一个单链表

  • 方法一:迭代
  • LeetCode刷题:链表_第2张图片
public ListNode reverseList(ListNode head) {
        if(head==null)
            return null;
        //此时链表至少有一个元素
        ListNode i=null,j=head,k=head.next; 
        while(k!=null){
            j.next = i;
            i=j;
            j=k;
            k=k.next;
        }
        j.next = i;
        return j; //返回翻转完的头指针
}
  • 方法二:递归
    LeetCode刷题:链表_第3张图片
public ListNode reverseList(ListNode head) {
	if(head==null || head.next ==null)
		return head;
	ListNode cur = reverseList(head.next);
	head.next.next = head;
	head.next =null;
	return cur; //返回翻转完的头指针
}

21. 合并两个有序链表

  • 类似于双指针的改版,关键是我们每次添加都是添加一个有值且指向null的节点,然后每次将当前节点的指针指向这个新创建的节点。
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        ListNode tmp = new ListNode(0); //一个头节点
        ListNode head = tmp;
        while(l1!=null && l2!=null){
            if(l1.val<=l2.val){
                tmp.next = new ListNode(l1.val,null);
                tmp=tmp.next;
                l1=l1.next;
            }
            else{
                tmp.next = new ListNode(l2.val,null);
                tmp=tmp.next;
                l2=l2.next;
            }
        }
        if(l1==null)
            tmp.next = l2;
        if(l2==null)
            tmp.next = l1;
        return head.next;
    }

你可能感兴趣的:(LeetCode,链表,数据结构,java)