1 public class ListNode {
2 public int val ;
3 public ListNode next;
4 public ListNode(int val) {
5 this.val = val;
6 this.next = null ;
7 }
8
9 }
1 /*
2 this is the implementation of LinkedList using the ListNode
3 * */
4 public class MyLinkedList {
5
6 //hide from direct access. only expose the methods
7 private ListNode head ;
8 private ListNode tail ;
9 private int length;
10
11 public MyLinkedList() {
12 this.head = null ;
13 this.tail = null ;
14 this.length = 0 ;
15 }
16 //=== since the head and tail are encapsulated, very improtant dont loose the head===
17 //1
18 public void appendHead(int value){
19 ListNode node = new ListNode(value) ;
20 node.next = head ;
21 head = node ;
22 length++ ;
23 syncHeadAndTail();
24 }
25
26 //2: 3->4->null 5
27 public void appendTail(int value){
28 if (head==null){
29 this.appendHead(value);
30 } else{
31 tail.next = new ListNode(value) ;
32 length++ ;
33 }
34 }
35
36 //=== assume there is no duplicate values
37 //corner case: no matching value
38 //3: 3->4-> null
39 public void remove(int value){
40 if (head == null) return ;
41 if (head.val == value){
42 head = head.next ; //corner case: 3-> null remove 3
43 length--;
44 syncHeadAndTail();
45 }
46 //1->3->null 3
47 else{
48 ListNode curr = head ;
49 ListNode pre = null ;
50 while (curr != null ){
51 pre = curr ;
52 curr = curr.next ;
53 if (curr.val == value){
54 pre.next = curr.next ;
55 length--;
56 syncHeadAndTail();
57 return;
58 }
59 }
60 }
61 }
62
63 //4: note here the length is length
64 public void removeIndex(int index){
65 //index >= length also covers the head == null case
66 if (index < 0 || index >= length) return;
67 //if remove at the head:
68 if (index == 0){
69 head = head.next ;
70 } else{
71 ListNode curr = head ;
72 for (int i = 0; i < index -1 ; i++) {
73 curr = curr.next ;
74 }
75 //special case for tail
76 if (index == length - 1){
77 tail = curr ;
78 }
79 curr.next = curr.next.next ;
80 }
81 length--;
82 syncHeadAndTail();
83 //if remove at the end: update the tail
84 }
85
86 private void syncHeadAndTail(){
87 if (length == 0){
88 head = null ;
89 tail = null ;
90 }
91 if (length == 1){
92 tail = head ;
93 }
94 }
95
96 //5: Integer get(int index): there would be chance return null. thats the reason we return wrapper
97 public Integer get(int index){
98 if (index < 0 || index >= length) return null;
99 ListNode curr = head ;
100 //one step short
101 for (int i = 0; i < index; i++) {
102 curr = curr.next ;
103 }
104 return curr.val ;
105 }
106 //6: Integer set(int index, int value): update by index. return the previous value
107 public Integer set(int index, int value){
108 if (index < 0 || index >= length) return null;
109 ListNode curr = head ;
110 //one step short
111 for (int i = 0; i < index; i++) {
112 curr = curr.next ;
113 }
114 int temp = curr.val ;
115 curr.val = value ;
116 return temp ;
117 }
118 //7: return the length: eager computation
119 public int size(){
120 return this.length;
121 }
122
123 //8:
124 public boolean isEmpty(){
125 return this.length > 0;
126 }
127
128 public static void main(String[] args) {
129 MyLinkedList list = new MyLinkedList();
130 list.appendHead(1);
131 list.appendHead(3);
132 list.appendTail(5);
133 System.out.println(list.size());
134 System.out.println(list.get(0));//3
135 System.out.println(list.get(2)); //5
136 list.set(5,6);
137 list.remove(1); //remove by value
138 System.out.println(list.size());//2
139 System.out.println(list.get(1)); //5
140 list.removeIndex(0);
141 System.out.println(list.get(0));//5
142 }
143 }