Largest permutation of elements in the range 1,....,N

Click For Summary

Discussion Overview

The discussion revolves around an algorithm designed to find the largest permutation of an array of integers from 1 to N using at most k swaps. Participants are analyzing the algorithm's performance and correctness, particularly in the context of a coding challenge on HackerRank.

Discussion Character

  • Technical explanation
  • Debate/contested
  • Homework-related

Main Points Raised

  • One participant notes that the algorithm has a time complexity of O(N²) and suggests the need for an O(N) solution.
  • Another participant expresses confusion about the algorithm's handling of swaps, indicating that issues may arise when trying to skip a swap.
  • There is a suggestion that dynamic programming concepts, particularly memoization, could improve the algorithm's efficiency.
  • Multiple participants report that the algorithm is still failing some test cases, with one participant mentioning that the input is guaranteed to be valid according to the problem specifications.
  • Concerns are raised about potential runtime errors and incorrect answers, with one participant suggesting that the code may be accessing invalid array objects.
  • A later reply points out a specific issue in the code where the decrementing of n may lead to incorrect behavior if not handled properly.

Areas of Agreement / Disagreement

Participants generally agree that the algorithm is not functioning as intended and that there are issues with its efficiency and correctness. However, there is no consensus on the exact nature of the problems or the best solutions to implement.

Contextual Notes

Participants note potential limitations in the algorithm related to assumptions about input validity, handling of duplicates or gaps in the input array, and the need for additional checks to prevent runtime errors.

SlurrerOfSpeech
Messages
141
Reaction score
11
with at most k swaps. (In other words, like the largest number formed by swapping k digits.)

Example. A=[4,2,3,5,1], k = 1 ---> [5,2,3,4,1]

I'm wondering why my algorithm is failing the test cases which I'm unable to see.

Code:
using System;
using System.Collections.Generic;
using System.IO;
class Solution
{
    public static void Swap(int[] A, int i1, int i2)
    {
        int temp = A[i1];
        A[i1] = A[i2];
        A[i2] = temp;
    }
    static void Main(String[] args)
    {
        int[] parameters = Array.ConvertAll(Console.ReadLine().Split(' '), Int32.Parse);
        int n = parameters[0];
        int k = parameters[1];
        int[] arr = Array.ConvertAll(Console.ReadLine().Split(' '), Int32.Parse);
        for(int i = 0; i < arr.Length && k > 0; ++i)
        {
           if(arr[i] == n) 
               continue;
           int j = arr.Length - 1;
           for(; j > i && arr[j] != n; --j);
            Swap(arr,i,j);
            --n;
            --k;
        }
        Console.WriteLine(string.Join(" ", arr));
    }
}
 
Technology news on Phys.org
Your algorithm is O(N2). You need to find an O(N) algorithm.
 
I think things go wrong when you try to skip a swap.

Edit: no, never mind. I misunderstood.
 
Last edited:
D H said:
Your algorithm is O(N2). You need to find an O(N) algorithm.
To make this clear, this is a hacker rank problem. Problem sites such as this focus solely on efficiency in the small, and in the process create rather artificial problems. This is an artificial problem.

As an alternative to beating yourself over the head on those artificial hacker rank problems, try looking into contributing to an existing open source project. There are many active open source projects at github and bitbucket, some of which are begging for help. So help. Along the way, you'll learn about version control, about the project, how to understand a large codebase, how to contribute to it, and how to test your contributions. This is much more worthwhile than solving one dynamic programming problem after another.

That said, dynamic programming comes into play in this problem. (This is an important concept you should learn.) DP oftentimes uses memoization. You haven't done that. You instead have that inner loop, which can be done away with by memoization. You haven't taken full advantage of the artificial nature of the problem, which is that the input sequence is a permutation of the integers between 1 and N (inclusive). Keep track of the indices of the values between 1 to N in an easily build array. Now when you swap, you need to swap index array elements as well as value array elements so that the index array always keeps in sync with the value array.Aside: DYAC, "memoization" is a word! Stop trying to change it to "memorization!"
 
  • Like
Likes   Reactions: Pepper Mint
D H said:
That said, dynamic programming comes into play in this problem. (This is an important concept you should learn.) DP oftentimes uses memoization. You haven't done that. You instead have that inner loop, which can be done away with by memoization. You haven't taken full advantage of the artificial nature of the problem, which is that the input sequence is a permutation of the integers between 1 and N (inclusive). Keep track of the indices of the values between 1 to N in an easily build array. Now when you swap, you need to swap index array elements as well as value array elements so that the index array always keeps in sync with the value array.

Ah, I see.

Lemme try this.
 
Hmm, this is still failing some of the test cases.

Code:
using System;
using System.Collections.Generic;
using System.IO;
class Solution
{
    public static void Swap(int[] A, int i1, int i2)
    {
        int temp = A[i1];
        A[i1] = A[i2];
        A[i2] = temp;
    }
    static void Main(String[] args)
    {
        int[] parameters = Array.ConvertAll(Console.ReadLine().Split(' '), Int32.Parse);
        int n = parameters[0];
        int k = parameters[1];
        int[] arr = Array.ConvertAll(Console.ReadLine().Split(' '), Int32.Parse);
        int[] pos = new int[n]; // pos[m-1] is the index of the value m in arr
        for(int i = 0; i < arr.Length; ++i)
        {
            pos[arr[i] - 1] = i;
        }
        for(int i = 0; i < arr.Length && k > 0; ++i, --n)
        {
           if(arr[i] == n)
               continue;
           int j = pos[n - 1];
           Swap(pos,arr[i]-1,n-1);
           Swap(arr,i,j);
           --k;
        }
        Console.WriteLine(string.Join(" ", arr));
    }
}
 
SlurrerOfSpeech said:
Hmm, this is still failing some of the test cases.

Code:
using System;
using System.Collections.Generic;
using System.IO;
class Solution
{
    public static void Swap(int[] A, int i1, int i2)
    {
        int temp = A[i1];
        A[i1] = A[i2];
        A[i2] = temp;
    }
    static void Main(String[] args)
    {
        int[] parameters = Array.ConvertAll(Console.ReadLine().Split(' '), Int32.Parse);
        int n = parameters[0];
        int k = parameters[1];
        int[] arr = Array.ConvertAll(Console.ReadLine().Split(' '), Int32.Parse);
        int[] pos = new int[n]; // pos[m-1] is the index of the value m in arr
        for(int i = 0; i < arr.Length; ++i)
        {
            pos[arr[i] - 1] = i;
        }
        for(int i = 0; i < arr.Length && k > 0; ++i, --n)
        {
           if(arr[i] == n)
               continue;
           int j = pos[n - 1];
           Swap(pos,arr[i]-1,n-1);
           Swap(arr,i,j);
           --k;
        }
        Console.WriteLine(string.Join(" ", arr));
    }
}
1. validate inputs
2. validate returned values from all methods
 
The input would be valid. The specs of the problem guarantee that. All the test cases expect for the 3 last ones are passing, and sometimes the failing ones fail with a Runtime Error and other times a Wrong Answer. I think HackerRank's C# engine is screwed up. I changed to Int64 and still getting errors.
 
SlurrerOfSpeech said:
The input would be valid. The specs of the problem guarantee that.
The specs might state so but the written code above I mean clearly isn't "guaranteed" to be bug-free.
All the test cases expect for the 3 last ones are passing, and sometimes the failing ones fail with a Runtime Error and other times a Wrong Answer. I think HackerRank's C# engine is screwed up. I changed to Int64 and still getting errors.
A lot of unknown errors related to runtime, it could be your code is accessing an invalid array object, for example. "Wrong Answer" is probably due to an incorrect implementation of your algorithm.
The probability that HackerRank system fails is also present but at least your code needs to be reworked with more guarding snippets to check all methods' returned values. Best practice is for the long road ahead in coding not for passing a pretty simple exercise of likely a test interview with a man-made system.
 
  • #10
If you are assuming no gaps or duplicates, then this seams to be the problem:
Java:
        for(int i = 0; i < arr.Length && k > 0; ++i)
        {
           // if this happens, then n is not decremented
           if(arr[i] == n)
               continue;
           int j = arr.Length - 1;

           // and then if n was not decremented last iteration
           // then n is at arr[i-1], so this loop will not find n, and will only result in j=i
           // so you will waste a swap, swapping arr[i] with itself
           for(; j > i && arr[j] != n; --j);
            Swap(arr,i,j);
            --n;
            --k;
        }

Otherwise, if gaps or duplicates are allowed, then there are more problems
 
  • Like
Likes   Reactions: Pepper Mint

Similar threads

  • · Replies 10 ·
Replies
10
Views
2K
  • · Replies 2 ·
Replies
2
Views
1K
  • · Replies 6 ·
Replies
6
Views
3K
  • · Replies 3 ·
Replies
3
Views
2K
  • · Replies 9 ·
Replies
9
Views
2K
  • · Replies 2 ·
Replies
2
Views
2K
  • · Replies 3 ·
Replies
3
Views
3K
  • · Replies 8 ·
Replies
8
Views
2K
  • · Replies 2 ·
Replies
2
Views
2K
  • · Replies 4 ·
Replies
4
Views
2K