diff --git a/scala/src/main/scala/ch07_linkedlist/LinkedListAlgo.scala b/scala/src/main/scala/ch07_linkedlist/LinkedListAlgo.scala index 5ca933c..d151bd5 100644 --- a/scala/src/main/scala/ch07_linkedlist/LinkedListAlgo.scala +++ b/scala/src/main/scala/ch07_linkedlist/LinkedListAlgo.scala @@ -89,6 +89,40 @@ object LinkedListAlgo { head } + def deleteLastKthNode(headOpt: Option[Node], k: Int): Option[Node] = { + require(k > 0, "k must greater than 0") + headOpt match { + case None => None + case Some(head) => + var index = 0 + var slow = headOpt + var fast = headOpt + while (fast.get.next.isDefined && index < k) { + //move fast cursor to k + fast = fast.get.next + index += 1 + } + + if (fast.get.next.isEmpty && index + 1 == k) { + //deleting the head element + return head.next + } + + require(index.equals(k), "given linked list should contains at least k elements ") + while (fast.get.next.isDefined) { + fast = fast.get.next + slow = slow.get.next + } + + //fast cursor is in the end of the chain + //slow is the previous pos of k element + //do the operation + slow.get.next = slow.get.next.get.next + } + + headOpt + } + //form all the chain value as string def mkStringForChain(node: Node): String = { val result = new StringBuilder diff --git a/scala/src/test/scala/ch07_linkedlist/LinkedListAlgoTest.scala b/scala/src/test/scala/ch07_linkedlist/LinkedListAlgoTest.scala index 360c7f4..84a1952 100644 --- a/scala/src/test/scala/ch07_linkedlist/LinkedListAlgoTest.scala +++ b/scala/src/test/scala/ch07_linkedlist/LinkedListAlgoTest.scala @@ -136,4 +136,73 @@ class LinkedListAlgoTest extends FlatSpec with Matchers { assert(node.isEmpty) } + it should "delete last 2nd element " in { + val list = new SinglyLinkedList() + + for (i <- 0 to 9) { + list.insertTail(i) + } + LinkedListAlgo.mkStringForChain(list.headOpt.get) should equal((0 to 9).toArray.mkString("")) + + val node = LinkedListAlgo.deleteLastKthNode(list.headOpt, 2) + assert(node.isDefined) + LinkedListAlgo.mkStringForChain(node.get) should equal("012345679") + } + + it should "delete last element " in { + val list = new SinglyLinkedList() + + for (i <- 0 to 9) { + list.insertTail(i) + } + LinkedListAlgo.mkStringForChain(list.headOpt.get) should equal((0 to 9).toArray.mkString("")) + + val node = LinkedListAlgo.deleteLastKthNode(list.headOpt, 1) + assert(node.isDefined) + LinkedListAlgo.mkStringForChain(node.get) should equal("012345678") + } + + it should "delete first element " in { + val list = new SinglyLinkedList() + + for (i <- 0 to 9) { + list.insertTail(i) + } + LinkedListAlgo.mkStringForChain(list.headOpt.get) should equal((0 to 9).toArray.mkString("")) + + val node = LinkedListAlgo.deleteLastKthNode(list.headOpt, 10) + assert(node.isDefined) + LinkedListAlgo.mkStringForChain(node.get) should equal("123456789") + } + + it should "delete firs only element " in { + val list = new SinglyLinkedList() + list.insertTail(0) + + val node = LinkedListAlgo.deleteLastKthNode(list.headOpt, 1) + assert(node.isEmpty) + } + + it should "throw exception if k < 0 " in { + val list = new SinglyLinkedList() + + for (i <- 0 to 9) { + list.insertTail(i) + } + assertThrows[IllegalArgumentException] { + LinkedListAlgo.deleteLastKthNode(list.headOpt, -1) + } + } + + it should "throw exception if k greater than list length " in { + val list = new SinglyLinkedList() + + for (i <- 0 to 9) { + list.insertTail(i) + } + assertThrows[IllegalArgumentException] { + LinkedListAlgo.deleteLastKthNode(list.headOpt, 15) + } + } + }