Related
I'm stuck in solving an interview question. The goal is to find a specific element from an array with unknown length (cannot use .length) and return the number of steps, but for an array with a length of n, the elements are guaranteed to be from 0 to n-1, no duplicates. For example, if the array's length is 5, the elements are {0, 1, 2, 3, 4} but the order may be different. Additional requirements are no loops, no static/global variables, and no helper functions, and the only parameters passing in are the array int[] arr and the target value int x, no extra parameters allowed, the array remains the same after all the operations have done.
//So you can only write in the body of the following method, no outside variables nor methods could be used.
private int findElement (int[] arr, int x) {
}
What I have gotten so far is, since the elements are guaranteed to be 0 to n-1, I can use the target number as an index and go back to the array to see if the number arr[x] equals the number x I want. If not, I take that number arr[x] and make it my new index, repeating until I find the target value.
int[] arr = {4, 1, 0, 2, 3}
int target = 3;
arr[3] = 2; //take target as the initial index
arr[2] = 0;
arr[0] = 4;
arr[4] = 3; //we got the number we want
//steps total is 3 since the question says the first time doesn't count.
Question: I tried to solve this by recursion, but since I am always comparing the following values with the initial parameter value, in the above case I always wanted to find 3. So how to store that information without static variables or extra parameters is my bigges problem. Is there any other way I can store the initial parameter value and pass it through the whole process?
private int findElement(int [] arr, int x) {
int actualN = arr[x];
if (actualN == **???**) { //can't be x cuz x is changing but I always want 3
return 0;
} else {
return findElement(arr, arr[x]) + 1;
}
}
Preferably using Java
Any hints or help would be greatly appreciated.
Probably this should work:
private int findElement(int [] arr, int x) {
int currValue = arr[x], returnValue;
if(arr[x]>0)
arr[x] = 0;//setting the actual element of the array to 0
else
arr[x]--;// decrementing the search index so it goes from 0-> -1 -> -2 -> -3...
if(Math.abs(arr[-arr[x]]) == x)//We check if the number is at our search index...
returnValue = 0;
else
returnValue = findElement(arr, x)+1;
arr[x] = currValue;//We take the value of the index from when the function was called and then reassign it to the same index after our work with it is done.
return returnValue;
}
Since the array only has to be the same after execution and it doesn't matter it's state during execution, this may work.
Note: I haven't done elaborate test on this so please do test the code sometimes before submitting
You were almost there
// t is the target number, o is teh array offset
static int find(int [] arr, int t, int o) {
if (arr[o] == t)
return o;
return find(arr, t, o + 1);
}
and
static void Main(string[] args) {
int[] arr = { 4, 1, 0, 2, 3 };
int target = 3;
int x = find(arr, 3, 0);
}
if only 2 args allowed - I missed that
in c
static int* find(int* arr, int t) {
if (*arr == t)
return arr;
return find(arr + 1, t);
}
int main() {
int arr[] = {4, 1, 0, 2, 3};
int target = 2;
int x = find(arr, target) - arr;
}
in c#
static unsafe int* find(int * arr, int t) {
if (*arr == t)
return arr;
return find(arr + 1,t);
}
static void Main(string[] args) {
int[] arr = { 4, 1, 0, 2, 3 };
int target = 3;
unsafe {
fixed (int * p = &arr[0]) {
int x = (int)(find(p, target) - p);
}
}
}
I have assumed arr can be modified, provide it is unchanged after the answer has been obtained.
Since it is only "preferable" that the answer be in Java (and I don't know Java), I'll offer a solution in Ruby. With its pseudo-code appearance and added comments readers unfamiliar with Ruby should be able to follow the calculations.
Specifically, I append an element to the given array which equals the index of the current element of the array to be examined (initially zero). If that element equals the target value we return up the recursion chain, initially returning zero, then adding one at each subsequent point of the chain. Before returning the desired count in doit, the last element of the array is removed to restore the array to its initial value.
If the value of the array indexed by the last element of the array (the current index) does not equal the target value the last element of the array is incremented by one and the method is called recursively.
def doit(arr,target)
arr << 0 # append the index 0 to arr
n = recurse(arr, target)
arr.pop # remove the last element of arr
n
end
def recurse(arr, target)
return 0 if arr[arr[-1]] == target
arr[-1] += 1 # increment last value of arr by 1
1 + recurse(arr, target)
end
arr = [4, 1, 0, 2, 3]
doit(arr, 4) #=> 0
doit(arr, 1) #=> 1
doit(arr, 0) #=> 2
doit(arr, 2) #=> 3
doit(arr, 3) #=> 4
I'm trying to make a code that removes all the elements from the array that are equal to a given value. For example an array = [hi, hello, hi, bye] value = hi, it would given an output hello bye
Here's my code:
int count = 0;
for(int i=0; i<stringArr.length;
if(stringArr[i].equals(value)){
count--;
for(int j= i; j<stringArr.length-1; j++){
stringArr[j] = stringArr[j+1];
}
i--;
}
}
Problem is instead of the expected output as: hello bye
It gives an output of:
hello hi bye bye
Try Java stream api:
String value = "hi";
String[] stringArr = new String[] {"hi", "hello", "hi", "bye"};
String[] results = Arrays.stream(stringArr)
.filter(it -> !it.equalsIgnoreCase(value))
.toArray(String[]::new);
The problem is that you are shifting the values left but not decrementing the length of the array in the outer for.
Assign stringArr.length to count and use it in the for.
Trading memory for speed, you could create a new array of the same length and only add in the first occurrence of what you want.
String[] removeEqual(String[]array,String val){
boolean found =false;
String[]out=new String[array.length];
int count=0;
for (int i=0;i<array.length;i++){
if(array[i].equals(val)){
if(!found){
out[count++]=val;
found=true;
}
else out[count++]=val;
}
}
return Arrays.copyOf(out, count);
}
You may like to consider separate functions for separate conditions such as removeLessThan and removeGreaterThan to keep it functionally coherent.
I don't recommend to do any manipulation to the original array, create a new one. Recycling is good for the planet, but may be very harmful in code. So if you want to stick to the Arrays only, then create a new array with and add all elements you want into the new array, but I think you can do better. Your approach is very "C" like, this is Java, you have a lot of better tools, than arrays.
One of them are streams and lambdas like this
#Test
public void example_lambdas() {
String[] array = {"hi", "hello", "hi", "bye"};
String[] result = Arrays.stream(array).filter(element -> !"hi".equals(element)).toArray(String[]::new);
System.out.println(Arrays.toString(result));
}
Another option is to use list
#Test
public void example_list() {
String[] array = {"hi", "hello", "hi", "bye"};
List<String> list = new ArrayList<>(Arrays.asList(array));
Set<String> toBeRemoved = Collections.singleton("hi");
list.removeAll(toBeRemoved);
String[] result = list.toArray(new String[0]);
System.out.println(Arrays.toString(result));
}
An array has a fixed size that cannot be changed. Hence your result cannot be a two element array when you start with a four element array. If you want the result to be a two element array, then you will need to create a second array. If, however, you want the result to stay in the original array, then I suggest setting the excess array elements to null. The following code demonstrates.
String[] stringArr = {"hi", "hello", "hi", "bye"};
String condition = "==";
String value = "hi";
int count = stringArr.length;
for (int i = 0; i < count; i++) {
if (condition.equals("==")) {
if (stringArr[i].equals(value)) {
count--;
for (int j = i; j < stringArr.length - 1; j++) {
stringArr[j] = stringArr[j + 1];
}
stringArr[stringArr.length - 1] = null;
}
}
}
System.out.println(java.util.Arrays.toString(stringArr));
The above code prints the following:
[hello, bye, null, null]
EDIT
As requested, below code creates a new array that only contains the requested elements, i.e. the ones that were not removed from the original array.
String[] stringArr = {"hi", "hello", "hi", "bye"};
String condition = "==";
String value = "hi";
String[] temp = new String[stringArr.length];
int count = 0;
for (int i = 0; i < stringArr.length; i++) {
if (condition.equals("==")) {
if (!stringArr[i].equals(value)) {
temp[count++] = stringArr[i];
}
}
}
String[] result = new String[count];
for (int i = 0; i < count; i++) {
result[i] = temp[i];
}
System.out.println(Arrays.toString(result));
The above code prints the following:
[hello, bye]
In other words, result is a two element array.
Note that I assume that you only want to do array manipulation and you don't want to use classes in the JDK that most of the other answers have used.
This program is for printing sum of all the numbers in the array given as input parameter. However this does not happen. Please let me know what is the mistake and provide me the solution with explanation.
namespace linkedLists
{
class Program
{
static void Main(string[] args)
{
int[] arr = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
int x = sumOfNum(arr, 0);
Console.WriteLine(x);
Console.ReadLine();
}
public static int sumOfNum(int[] arr, int x)
{
int[] arr_new = new int[arr.Length - 1];
if (arr.Length > 1)
{
x += arr[arr.Length - 1];
for (int i = 0; i < arr.Length - 1; i++)
{
arr_new[i] = arr[i];
}
}
if (arr.Length > 1)
{
sumOfNum(arr_new, x);
}
return x;
}
}
}
Your question's title is "how to avoid a return statement in recursion", which is exactly what you should be doing instead of avoiding in a recursion scenario.
But this is not the only problem with your code, because it does nothing like what you described it is supposed to do.
As already mentioned in the comments, this is not something that requires (or for which it is recommended) to use a recursive approach. It can be done, but is inefficient and could lead to a stack overflow if you have a large input array (it needs a new stack frame for each recursive method call in c#).
To solve this recursively, you need to try and state the problem as a recursive problem, before you start trying to code it. In pseudo code, for an input array x of size n:
array_sum(x):
if (x is empty)
return 0;
else
return x[0] + array_sum(x[1:n-1])
An implementation in C# would try to avoid allocating a new array instance (as opposed to what one of the non-functioning parts in the code of your question is doing), and instead keep track of the start index into the input array:
public static array_sum(int startIndex, int[] x)
{
// ...
}
If you want to know the answer without the recursion you just iterate over it while summing the numbers.
If you want to make a recursive solution the return is essential. Without it the recursion is just a different way of making a for loop.
public static int sumOfElements(int[] arr, int currentIndex, int accumulator)
{
if( finished-expression )
return accumulator;
else
return sumOfElements(...);
}
public static int sumOfElements(int[] arr)
{
return sumOfelements(arr, 0, 0);
}
Your mistake is that x is a different one at each iteration. You don't use the returned value from the recursion so you have the sum of one element as the result.
Agree with the previous comments about recursion, inefficiency, and complexity but as an exercise below is the minimal number changes to get the code to work.
Changes:
Added array size guard
Moved sum out of if-block
Added return statement
Code:
namespace linkedLists
{
class Program
{
static void Main(string[] args)
{
int[] arr = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
int x = sumOfNum(arr, 0);
Console.WriteLine(x);
Console.ReadLine();
}
public static int sumOfNum(int[] arr, int x)
{
if (arr.Length == 0) return x; // Change #1
int[] arr_new = new int[arr.Length - 1];
x += arr[arr.Length - 1]; // Change #2
if (arr.Length > 1)
{
for (int i = 0; i < arr.Length - 1; i++)
{
arr_new[i] = arr[i];
}
}
if (arr.Length > 1)
{
return sumOfNum(arr_new, x); // Change #3
}
return x;
}
}
}
Assuming that you are required to use recursion as an exercise I will comment no further on that.
The reason your programme does not work appears to be that when the array has only one element, your do not add that element to the subtotal (that you call x) before returning it.
While recursion is somewhat expensive, your program uses roughly ½arr.Length² ints, which would need a terabyte of memory in the unlikely event that you applied it to an array of length 500,000! So you would be far better not to copy the array.
I think it is basically an easy problem, but I'm stuck. My brain is blocked by this problem, so I hope you can help me.
I have 2 to N arrays of integers, like
{1,2,3,4,5}
{1,2,3,4,5,6}
{1,3,5}
.....
Now i want to have a list containing arrays of int[N] with every posibillity like
{1,1,1}
{1,1,3}
{1,1,5}
{1,2,1}
....
{1,3,1}
....
{2,1,1}
{2,1,3}
....
{5,6,5}
so there are 6*5*3 (90) elements in it.
Is there a simple algorithm to do it? I think the language didn't matter but I prefer Java.
Thx for the help!
I add a valid answer with the implementation in java for the next guy, who has the same problem. I also do it generic so u can have any CartesianProduct on any Object, not just ints:
public class Product {
#SuppressWarnings("unchecked")
public static <T> List<T[]> getCartesianProduct(T[]... objects){
List<T[]> ret = null;
if (objects != null){
//saves length from first dimension. its the size of T[] of the returned list
int len = objects.length;
//saves all lengthes from second dimension
int[] lenghtes = new int[len];
// arrayIndex
int array = 0;
// saves the sum of returned T[]'s
int lenSum = 1;
for (T[] t: objects){
lenSum *= t.length;
lenghtes[array++] = t.length;
}
//initalize the List with the correct lenght to avoid internal array-copies
ret = new ArrayList<T[]>(lenSum);
//reusable class for instatiation of T[]
Class<T> clazz = (Class<T>) objects[0][0].getClass();
T[] tArray;
//values stores arrayIndexes to get correct values from objects
int[] values = new int[len];
for (int i = 0; i < lenSum; i++){
tArray = (T[])Array.newInstance(clazz, len);
for (int j = 0; j < len; j++){
tArray[j] = objects[j][values[j]];
}
ret.add(tArray);
//value counting:
//increment first value
values[0]++;
for (int v = 0; v < len; v++){
//check if values[v] doesn't exceed array length
if (values[v] == lenghtes[v]){
//set it to null and increment the next one, if not the last
values[v] = 0;
if (v+1 < len){
values[v+1]++;
}
}
}
}
}
return ret;
}
}
As i understand what you want, you need to get all permutations.
Use recursive algorithm, detailed here.
As I see this should work fine:
concatMap (λa -> concatMap (λb -> concatMap (λc -> (a,b,c)) L3) L2) L1
where concatMap(called SelectMany in C#) is defined as
concatMap f l = concat (map f l).
and map maps a function over a list
and concat(sometimes called flatten) takes a List of List and turns it into a flat List
I'm not sure how to ask my question in a succinct way, so I'll start with examples and expand from there. I am working with VBA, but I think this problem is non language specific and would only require a bright mind that can provide a pseudo code framework. Thanks in advance for the help!
Example:
I have 3 Character Arrays Like So:
Arr_1 = [X,Y,Z]
Arr_2 = [A,B]
Arr_3 = [1,2,3,4]
I would like to generate ALL possible permutations of the character arrays like so:
XA1
XA2
XA3
XA4
XB1
XB2
XB3
XB4
YA1
YA2
.
.
.
ZB3
ZB4
This can be easily solved using 3 while loops or for loops. My question is how do I solve for this if the # of arrays is unknown and the length of each array is unknown?
So as an example with 4 character arrays:
Arr_1 = [X,Y,Z]
Arr_2 = [A,B]
Arr_3 = [1,2,3,4]
Arr_4 = [a,b]
I would need to generate:
XA1a
XA1b
XA2a
XA2b
XA3a
XA3b
XA4a
XA4b
.
.
.
ZB4a
ZB4b
So the Generalized Example would be:
Arr_1 = [...]
Arr_2 = [...]
Arr_3 = [...]
.
.
.
Arr_x = [...]
Is there a way to structure a function that will generate an unknown number of loops and loop through the length of each array to generate the permutations? Or maybe there's a better way to think about the problem?
Thanks Everyone!
Recursive solution
This is actually the easiest, most straightforward solution. The following is in Java, but it should be instructive:
public class Main {
public static void main(String[] args) {
Object[][] arrs = {
{ "X", "Y", "Z" },
{ "A", "B" },
{ "1", "2" },
};
recurse("", arrs, 0);
}
static void recurse (String s, Object[][] arrs, int k) {
if (k == arrs.length) {
System.out.println(s);
} else {
for (Object o : arrs[k]) {
recurse(s + o, arrs, k + 1);
}
}
}
}
(see full output)
Note: Java arrays are 0-based, so k goes from 0..arrs.length-1 during the recursion, until k == arrs.length when it's the end of recursion.
Non-recursive solution
It's also possible to write a non-recursive solution, but frankly this is less intuitive. This is actually very similar to base conversion, e.g. from decimal to hexadecimal; it's a generalized form where each position have their own set of values.
public class Main {
public static void main(String[] args) {
Object[][] arrs = {
{ "X", "Y", "Z" },
{ "A", "B" },
{ "1", "2" },
};
int N = 1;
for (Object[] arr : arrs) {
N = N * arr.length;
}
for (int v = 0; v < N; v++) {
System.out.println(decode(arrs, v));
}
}
static String decode(Object[][] arrs, int v) {
String s = "";
for (Object[] arr : arrs) {
int M = arr.length;
s = s + arr[v % M];
v = v / M;
}
return s;
}
}
(see full output)
This produces the tuplets in a different order. If you want to generate them in the same order as the recursive solution, then you iterate through arrs "backward" during decode as follows:
static String decode(Object[][] arrs, int v) {
String s = "";
for (int i = arrs.length - 1; i >= 0; i--) {
int Ni = arrs[i].length;
s = arrs[i][v % Ni] + s;
v = v / Ni;
}
return s;
}
(see full output)
Thanks to #polygenelubricants for the excellent solution.
Here is the Javascript equivalent:
var a=['0'];
var b=['Auto', 'Home'];
var c=['Good'];
var d=['Tommy', 'Hilfiger', '*'];
var attrs = [a, b, c, d];
function recurse (s, attrs, k) {
if(k==attrs.length) {
console.log(s);
} else {
for(var i=0; i<attrs[k].length;i++) {
recurse(s+attrs[k][i], attrs, k+1);
}
}
}
recurse('', attrs, 0);
EDIT: Here's a ruby solution. Its pretty much the same as my other solution below, but assumes your input character arrays are words: So you can type:
% perm.rb ruby is cool
~/bin/perm.rb
#!/usr/bin/env ruby
def perm(args)
peg = Hash[args.collect {|v| [v,0]}]
nperms= 1
args.each { |a| nperms *= a.length }
perms = Array.new(nperms, "")
nperms.times do |p|
args.each { |a| perms[p] += a[peg[a]] }
args.each do |a|
peg[a] += 1
break if peg[a] < a.length
peg[a] = 0
end
end
perms
end
puts perm ARGV
OLD - I have a script to do this in MEL, (Maya's Embedded Language) - I'll try to translate to something C like, but don't expect it to run without a bit of fixing;) It works in Maya though.
First - throw all the arrays together in one long array with delimiters. (I'll leave that to you - because in my system it rips the values out of a UI). So, this means the delimiters will be taking up extra slots: To use your sample data above:
string delimitedArray[] = {"X","Y","Z","|","A","B","|","1","2","3","4","|"};
Of course you can concatenate as many arrays as you like.
string[] getPerms( string delimitedArray[]) {
string result[];
string delimiter("|");
string compactArray[]; // will be the same as delimitedArray, but without the "|" delimiters
int arraySizes[]; // will hold number of vals for each array
int offsets[]; // offsets will holds the indices where each new array starts.
int counters[]; // the values that will increment in the following loops, like pegs in each array
int nPemutations = 1;
int arrSize, offset, nArrays;
// do a prepass to find some information about the structure, and to build the compact array
for (s in delimitedArray) {
if (s == delimiter) {
nPemutations *= arrSize; // arrSize will have been counting elements
arraySizes[nArrays] = arrSize;
counters[nArrays] = 0; // reset the counter
nArrays ++; // nArrays goes up every time we find a new array
offsets.append(offset - arrSize) ; //its here, at the end of an array that we store the offset of this array
arrSize=0;
} else { // its one of the elements, not a delimiter
compactArray.append(s);
arrSize++;
offset++;
}
}
// put a bail out here if you like
if( nPemutations > 256) error("too many permutations " + nPemutations+". max is 256");
// now figure out the permutations
for (p=0;p<nPemutations;p++) {
string perm ="";
// In each array at the position of that array's counter
for (i=0;i<nArrays ;i++) {
int delimitedArrayIndex = counters[i] + offsets[i] ;
// build the string
perm += (compactArray[delimitedArrayIndex]);
}
result.append(perm);
// the interesting bit
// increment the array counters, but in fact the program
// will only get to increment a counter if the previous counter
// reached the end of its array, otherwise we break
for (i = 0; i < nArrays; ++i) {
counters[i] += 1;
if (counters[i] < arraySizes[i])
break;
counters[i] = 0;
}
}
return result;
}
If I understand the question correctly, I think you could put all your arrays into another array, thereby creating a jagged array.
Then, loop through all the arrays in your jagged array creating all the permutations you need.
Does that make sense?
it sounds like you've almost got it figured out already.
What if you put in there one more array, call it, say ArrayHolder , that holds all of your unknown number of arrays of unknown length. Then, you just need another loop, no?