简体   繁体   中英

Add k to the kTh node, starting from the end Recursively

Given a linked list of integers and a number, k, add k to every kth node starting from the end. For example, if the list is [1 -> 2 -> 3 -> 4] and k is 3, then the result is [1 -> 5 -> 3 -> 4]. The 2 was the third value from the end, we added three to get 5. No other nodes are modified.

For a longer example, consider the list:

[1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7] If k=3, two nodes change:

[1 -> 5 -> 3 -> 4 -> 8 -> 6 -> 7]

Here's what I have so far, but I should probably be using some pointers and I can't figure out how to add k to the kth element once we reach it.

function solution(head, k) {

  if(head == null) return head;

  if(head.next) {
    for(let i = 0; i < k; i++) {
    return solution(head.next, k)
  }
return head;
}

If you do not know the length or end node of the linked list, then you first need to find it by looping through it. From there, you can then loop through the linked list again and add k to the node's value if the length minus the node's index is divisible by k . Like this:

function solution(head, k) {
  // Get length of the list
  let len = 0;
  let ptr = head;
  while (ptr !== null) {
    ptr = ptr.next;
    len++;
  }

  // Loop through list and change nodes
  // with indices that satisfy condition
  ptr = head;
  let i = 0;
  while (ptr !== null) {
    if ((len-i) % k === 0) ptr.value += k;
    i++;
    ptr = ptr.next;
  }
  return head;
} 

The crux of the code is this line:

if ((len-i) % k === 0) ptr.value += k;

len-i represents the i th index starting from the end, and the % k gets the remainder when divided by k , so if the remainder is zero (thus divisible), we want to add k to the node's value.

Note: My code assumes the value of the node is stored in the .value property. You may need to change this.

You can get the length of the linked list, then calculate which nodes to increment based on their indexes.

 function arrToLinkedList(arr) { let head = arr.length? {value: arr[0]}: null, curr = head; for (let i = 1; i < arr.length; i++) curr.next = {value: arr[i]}, curr = curr.next; return head; } function linkedListToArr(head) { const res = []; for (let curr = head; curr; curr = curr.next) res.push(curr.value); return res; } function solution(head, k) { let len = 0, curr = head; while (curr) ++len, curr = curr.next; curr = head; for (let i = 0; i < len - 1; i++) { if ((len - i) % k === 0) curr.value += k; curr = curr.next; } return head; } console.log(linkedListToArr(solution(arrToLinkedList([1, 2, 3, 4, 5, 6, 7]), 3)));

The basic idea is to do

function length(head) {
  if (head == null) return 0;
  else return 1 + length(head.next);
}
function solution(head, k) {
  if (head == null) return null;
  else if (length(head) == k) return {value: head.value+k, next: head.next};
  else return {value: head.value, next: solution(head.next, k)};
}

However, this is really inefficient, since calling length on every list element gets us quadratic time complexity. The trick is to use a helper function that returns the length and the updated list together:

function helper(head, k) {
  if (head == null) return [0, null];
  const [length, rest] = helper(head.next, k);
  if (length == k) return [length+1, {value: head.value+k, next: rest}];
  else return [length+1, {value: head.value, next: rest}];
}
function solution(head, k) {
  return helper(head, k)[1];
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM