Rotate Array

Problem Statement

LeetCode#189

Given an integer array nums, rotate the array to the right by k steps, where k is non-negative.

Example 1

Input: nums = [1,2,3,4,5,6,7], k = 3
Output: [5,6,7,1,2,3,4]
Explanation:
rotate 1 steps to the right: [7,1,2,3,4,5,6]
rotate 2 steps to the right: [6,7,1,2,3,4,5]
rotate 3 steps to the right: [5,6,7,1,2,3,4]

Example 2

Input: nums = [-1,-100,3,99], k = 2
Output: [3,99,-1,-100]
Explanation: 
rotate 1 steps to the right: [99,-1,-100,3]
rotate 2 steps to the right: [3,99,-1,-100]

Constraints

  • 1 <= nums.length <= 105
  • -231 <= nums[i] <= 231 - 1
  • 0 <= k <= 105

Solution

Using an Auxiliary Array (O(n) Extra Space)

In this approach, you create a temporary array to hold the rotated version of the array, then copy it back into the original array. While this solution uses O(n) extra space, it is simple and clear.

This solution runs in O(n) time but uses O(n) extra space.

Steps

  1. Create a new array of the same size.
  2. For each element, calculate its new index after rotation.
  3. Copy the rotated elements back into the original array.
func rotate(nums []int, k int) {
    n := len(nums)
    k = k % n
    tmp := make([]int, n)

    for i := 0; i < n; i++ {
        tmp[(i + k) % n] = nums[i]
    }

    // Copy elements back into original array
    copy(nums, tmp)
}

Golang Code Rotate Array

func rotate(nums []int, k int)  {
    index := 0
    counter := 0
    length := len(nums)
    tmp := nums[0]

    if length == 1 || k==0 || length == k || k > (10*10*10*10*10) || length > (10*10*10*10*10) {
        return
    }
    
    seen := map[int]bool{0:true}
    for j:=0 ;counter < length ; j++{
        n := index + k
        if index+k >= length {
            n = (index+k) % length
        }
        nums[n], tmp = tmp, nums[n]
        index = n
        if seen[n]{
            index = n+1
            seen[n+1]= true
            tmp=nums[index]
        }else{
            seen[n]= true
        }
        counter++
    }
}

Cyclic Replacements (O(1) Extra Space)

After restructuring above Code

This method moves elements one by one to their new positions in a cyclic manner. The idea is to track where each element should go and keep swapping them in place until all elements have been rotated.

This solution works in O(n) time and uses O(1) extra space.

Steps

  1. Start from the first element, move it to its new position after rotation.
  2. Continue this for each element, using a temporary variable to hold values as they are swapped.
func rotate(nums []int, k int) {
    n := len(nums)
    k = k % n
    count := 0  // Number of elements moved

    for start := 0; count < n; start++ {
        current := start
        prev := nums[start]

        for {
            next := (current + k) % n
            nums[next], prev = prev, nums[next]
            current = next
            count++

            if start == current {
                break
            }
        }
    }
}

Optimised Golang Code for Rotate Array

func rotate(nums []int, k int) {
    length := len(nums)

    // Handle trivial cases
    if length == 1 || k == 0 || k%length == 0 {
        return
    }

    // Optimize k to avoid unnecessary full cycles
    k = k % length

    index := 0
    counter := 0
    tmp := nums[0]
    seen := map[int]bool{0: true}

    for counter < length {
        n := (index + k) % length
        nums[n], tmp = tmp, nums[n]
        index = n

        if seen[index] {
            index++
            tmp = nums[index]
            seen[index] = true
        } else {
            seen[index] = true
        }
        counter++
    }
}

Follow up

  • Try to come up with as many solutions as you can. There are at least three different ways to solve this problem.
  • Could you do it in-place with O(1) extra space?

In-Place Reversal Algorithm (O(1) Extra Space)

This is an efficient way to solve the problem using the reversal technique. It achieves O(1) extra space and works in O(n) time.

Steps

  1. Reverse the entire array.
  2. Reverse the first k elements.
  3. Reverse the last n-k elements.
func reverse(nums []int, start, end int) {
    for start < end {
        nums[start], nums[end] = nums[end], nums[start]
        start++
        end--
    }
}

func rotate(nums []int, k int) {
    n := len(nums)
    k = k % n  // Handle cases where k is larger than n

    // Step 1: Reverse the entire array
    reverse(nums, 0, n-1)
    
    // Step 2: Reverse the first k elements
    reverse(nums, 0, k-1)
    
    // Step 3: Reverse the remaining n-k elements
    reverse(nums, k, n-1)
}

Summary

  • In-place reversal: O(n) time and O(1) space.
  • Cyclic replacements: O(n) time and O(1) space.
  • Auxiliary array: O(n) time and O(n) space.

The first two solutions meet the requirement of O(1) extra space, while the third uses more space but is simple to implement.

Visit https: https://codeandalgo.com for more such contents.

Leave a Reply

Your email address will not be published. Required fields are marked *