【代码随想录】day03 203.移除链表元素 707.设计链表 206.反转链表

移除链表元素

leetcode: 203.移除链表元素.

拿到题目的思考

首先得清楚java内部的链表结构的实现。leetcode给我们提供了一个可以使用的简单模型:

  public class ListNode {
      int val;
      ListNode next;
      ListNode() {}
      ListNode(int val) { this.val = val; }
      ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 }

移除链表元素,本质上就是将当前元素的前一个元素的指针指向它的下一个元素。如果移除的元素是链表的第一个元素,就使用第二个元素作为第一个元素。

观看教程后的思考

因为第一个元素的特殊性,所以会考虑可不可以对整个流程进行统一处理,所以会产生两种解法:
1.生成一个虚拟的头结点,它的存在就是为了让第一个头结点移除逻辑和其他节点相同。

class Solution {
    public ListNode removeElements(ListNode head, int val) {
		ListNode moakPre = new ListNode(-1,head);
		ListNode cur = moakPre;
		while (cur!=null){
			if (cur.next!=null&&cur.next.val==val){
				cur.next=cur.next.next;
			}else{
				cur = cur.next;
			}
		}
		return moakPre.next;
	}
}

2.分开处理两套逻辑

class Solution {
    public ListNode removeElements(ListNode head, int val) {
		while (head!=null&&val== head.val){
			head=head.next;
		}
		ListNode curr = head;
		while(curr!=null){
			while (curr.next!=null&&curr.next.val==val){
				curr.next = curr.next.next;
			}
			curr = curr.next;
		}
		return head;
	}
}

因为java并没有指针,我们使用引用切换当前迭代的节点信息。需要注意判断的时机和切换的点。

设计链表

leetcode: 707. 设计链表.

拿到题目的思考

首先按照如下方式进行了设计:

class MyLinkedList {

    public Node node;

    private class Node {
        public int val;
        public Node next;

        public Node() {
        }

        public Node(int val, Node next) {
            this.val  = val;
            this.next = next;
        }
    }

    public MyLinkedList() {
        node = new Node(-1,null);
    }

    public int get(int index) {
        int curIndex = 1;
        int result = -1;
        Node cur = node;
        while (cur != null) {
            if (curIndex++ == index) {
                result = cur.val;
            }
            cur = cur.next;
        }
        return result;
    }

    public void addAtHead(int val) {
        node = new Node(val, node);
    }

    public void addAtTail(int val) {
        Node cur = node;
        while (cur != null) {
            if (cur.next == null) {
                Node tail = new Node(val, null);
                cur.next = tail;
            }
            cur = cur.next;
        }
    }

    public void addAtIndex(int index, int val) {
        if (index == 1) {
            addAtHead(val);
        }
        Node cur = node;
        int curIndex = 2;
        while (cur != null) {
            if (curIndex == index) {
                Node tail = new Node(val, cur.next.next);
                cur.next = tail;
            }
            cur = cur.next;
        }
    }

    public void deleteAtIndex(int index) {
        if (index == 1) {
            node = node.next;
        }
        Node cur = node;
        int curIndex = 2;
        while (cur != null) {
            if (curIndex == index) {
                cur.next = cur.next.next;
            }
            cur = cur.next;
        }
    }
}

结果测试时显示超出内存限制了。个人感觉是循环判断的节点出了问题。反复查证后并未发现比较好的方法解决这个问题。索性引入size来进行循环判断,抛弃while。
修改后的方式:

class MyLinkedList {

        public Node head;
        public int size;

        private class Node {
            public int val;
            public Node next;

            public Node() {
            }

            public Node(int val) {
                this.val = val;
            }
        }

        public MyLinkedList() {
            size = 0;
            head = new Node(0);
        }

        public int get(int index) {
            if (index < 0 || index > size - 1) {
                return -1;
            }
            Node cur = head.next;
            for (int i = 0; i < index; i++) {
                cur = cur.next;
            }
            return cur.val;
        }

        public void addAtHead(int val) {
            addAtIndex(0, val);
        }

        public void addAtTail(int val) {
            addAtIndex(size, val);
        }

        public void addAtIndex(int index, int val) {
            if (index < 0) {
                index = 0;
            }
            if (index > size) {
                return;
            }
            Node cur = head;
            Node newNode = new Node(val);
            for (int i = 0; i < index; i++) {
                cur = cur.next;
            }

            newNode.next = cur.next;
            cur.next = newNode;
            size++;

        }

        public void deleteAtIndex(int index) {
            if (index < 0 || index >= size) {
                return;
            }
            Node cur = head;
            for (int i = 0; i < index; i++) {
                cur = cur.next;
            }
            cur.next = cur.next.next;
            size--;
        }
    }

看完教程的思考

题目中有一个很容易产生歧义的地方:第几个元素,居然会出现第0个。

反转链表

leetcode: 206.反转链表 .

拿到题目的思考

一开始写的时候发生了回环问题。因为链表和数组不同,链表上存储的全都是引用(指针),所以简单的反转会将后续的长链都引用过来,所以需要一个新的空节点对原来的值进行存储,思考以后代码如下:

class Solution {
    public ListNode reverseList(ListNode head) {
		if(head==null){
			return head;
		}
		ListNode temp = new ListNode(head.val,null);
		ListNode cur = head.next;
		while (cur!=null){
			ListNode preTemp = new ListNode(cur.val,temp);
			temp = preTemp;
			cur = cur.next;
		}
		return temp;
    }
}

观看教程后的思考

我上面写的代码其实是变种的双指针,使用temp保存后一个节点指针,用preTemp保存前一个节点指针。也可以使用递归法解决该问题:

class Solution {
    public ListNode reverseList(ListNode head) {
		return reverse(null,head);
    }

	private ListNode reverse(ListNode pre,ListNode cur){
		if(cur==null){
			return pre;
		}
		ListNode temp = null;
		temp = cur.next;
		cur.next = pre;
		return reverse(cur,temp);
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值