I have an array which have 1 2 3 4 5 values.
array a = [ 1 , 2, 3, 4, 5]
Now i want to traverse it in circular manner.
like i want to print 2 3 4 5 1 or 3 4 5 1 2 or 5 1 2 3 4 and so on.
any algorithm on this?
Edit: I want to print all the combination in circular manner. i don't want to state starting point at its initial phase.
int start = ...
for (int i = 0; i < a.length; i++) {
System.out.println(a[(start + i) % a.length]);
}
(If you want to iterate the array backwards from start, change start + i to start - i in the array subscript expression.)
I should note that this is probably not the most efficient way of expressing the loop ... in terms of execution speed. However, the difference is small, and most likely irrelevant.
A more relevant point is whether using % in this way gives more readable code. I think it does, but maybe that's because I've seen / used this particular idiom before.
How about the following:
int start = // start position, must be in bounds
int i = start;
do {
....
i++;
if(i == a.length) i = 0;
} while(i != start);
int st = n ; // n is the starting position from where you print
for(int i = st; i < a.length; i++)
{
-- print each array[i];
}
if(st != 0)
{
for(int i = 0 ; i < st ; i++)
{
--- print each array[i];
}
}
Basically you just need to loop through the array, and change the current index if necessary (like move it to the start of the array when it meets the end)
public static void main(String[] args) {
int[] array = new int[] { 1, 2, 3, 4, 5 };
System.out.println(printCircularly(array, 4));
}
private static String printCircularly(int[] array, int startIndex) {
StringBuilder sb = new StringBuilder();
int currentIndex = startIndex;
do {
sb.append(array[currentIndex++]);
if (currentIndex > array.length - 1) {
currentIndex = 0;
}
}
while (currentIndex != startIndex);
return sb.toString();
}
In addition to Stephen C's answer
int start = ...
for (int i = 0; i < a.length; i++) {
System.out.println(a[(start - i + a.length) % a.length]);
}
Use this for reverse loop from start index. It's a little unclear, but in some cases very useful. For example: UI components like carousel.
And there's no ArrayIndexOutOfBoundsException!!!
Instead of using a for loop with indexes, which is harder to read, you can use Iterables from Google Guava as follows :
List<Integer> myList = List.of(1,2,3);
Iterator<Integer> myListIterator = Iterables.cycle(myList).iterator();
then you will only have to use myListIterator.next(). example :
System.out.println(myListIterator.next());
System.out.println(myListIterator.next());
System.out.println(myListIterator.next());
System.out.println(myListIterator.next());
This will print : 1 2 3 1
Related
For part of an assignment, I have to create a method that merges 2 arrays into one sorted array in ascending order. I have most of it done, but I am getting a bug that replaces the last element in the array with 0. Has anyone ever run into this problem and know a solution? Heres my code:
public static OrderedArray merge(OrderedArray src1, OrderedArray src2) {
int numLength1 = src1.array.length;
int numLength2 = src2.array.length;
//combined array lengths
int myLength = (numLength1 + numLength2);
// System.out.println(myLength);
OrderedArray mergedArr = new OrderedArray(myLength);
//new array
long[] merged = new long[myLength];
//loop to sort array
int i = 0;
int j = 0;
int k = 0;
while (k < src1.array.length + src2.array.length - 1) {
if(src1.array[i] < src2.array[j]) {
merged[k] = src1.array[i];
i++;
}
else {
merged[k] = src2.array[j];
j++;
}
k++;
}
//loop to print result
for(int x = 0; x < myLength; x++) {
System.out.println(merged[x]);
}
return mergedArr;
}
public static void main(String[] args) {
int maxSize = 100; // array size
// OrderedArray arr; // reference to array
OrderedArray src1 = new OrderedArray(4);
OrderedArray src2 = new OrderedArray(5);
// arr = new OrderedArray(maxSize); // create the array
src1.insert(1); //insert src1
src1.insert(17);
src1.insert(42);
src1.insert(55);
src2.insert(8); //insert src2
src2.insert(13);
src2.insert(21);
src2.insert(32);
src2.insert(69);
OrderedArray myArray = merge(src1, src2);
This is my expected output:
1
8
13
17
21
32
42
55
69
and this is my current output:
1
8
13
17
21
32
42
55
0
While merging two arrays you are comparing them, sorting and merging but what if the length of two arrays is different like Array1{1,3,8} and Array2{4,5,9,10,11}. Here we will compare both arrays and move the pointer ahead, but when the pointer comes at 8 in array1 and at 9 in array2, now we cannot compare ahead, so we will add the remaining sorted array;
Solution:-
(Add this code between loop to sort array and loop to print array)
while (i < numLength1) {
merged[k] = src1.array[i];
i++;
k++;
}
while (j < numLength2) {
merged[k] = src2.array[j];
j++;
k++;
}
To answer your main question, the length of your target array is src1.array.length + src2.array.length, so your loop condition should be one of:
while (k < src1.array.length + src2.array.length) {
while (k <= src1.array.length + src2.array.length - 1) {
Otherwise, you will never set a value for the last element, where k == src1.array.length + src2.array.length - 1.
But depending on how comprehensively you test the code, you may then find you have a bigger problem: ArrayIndexOutOfBoundsException. Before trying to use any array index, such as src1.array[i], you need to be sure it is valid. This condition:
if(src1.array[i] < src2.array[j]) {
does not verify that i is a valid index of src1.array or that j is a valid index of src2.array. When one array has been fully consumed, checking this condition will cause your program to fail. You can see this with input arrays like { 1, 2 } & { 1 }.
This revision of the code does the proper bounds checks:
if (i >= src1.array.length) {
// src1 is fully consumed
merged[k] = src2.array[j];
j++;
} else if (j >= src2.array.length || src1.array[i] < src2.array[j]) {
// src2 is fully consumed OR src1's next is less than src2's next
merged[k] = src1.array[i];
i++;
} else {
merged[k] = src2.array[j];
j++;
}
Note that we do not need to check j in the first condition because i >= src1.array.length implies that j is a safe value, due to your loop's condition and the math of how you are incrementing those variables:
k == i + j due to parity between k's incrementing and i & j's mutually exclusive incrementing
k < src1.array.length + src2.array.length due to the loop condition
Therefore i + j < src1.array.length + src2.array.length
If both i >= src1.array.length and j >= src2.array.length then i + j >= src1.array.length + src2.array.length, violating the facts above.
A couple other points and things to think about:
Be consistent with how you refer to data. If you have variables, use them. Either use numLength1 & numLength2 or use src1.length & src2.length. Either use myLength or use src1.array.length + src2.array.length.
Should a merge method really output its own results, or should the code that called the method (main) handle all the input & output?
Is the OrderedArray class safe to trust as "ordered", and is it doing its job properly, if you can directly access its internal data like src1.array and make modifications to the array?
The best way to merge two arrays without repetitive items in sorted order is that insert both of them into treeSet just like the following:
public static int[] merge(int[] src1, int[] src2) {
TreeSet<Integer> mergedArray= new TreeSet<>();
for (int i = 0; i < src1.length; i++) {
mergedArray.add(src1[i]);
}
for (int i = 0; i < src2.length; i++) {
mergedArray.add(src2[i]);
}
return mergedArray.stream().mapToInt(e->(int)e).toArray();
}
public static void main(String[] argh) {
int[] src1 = {1,17,42,55};
int[] src2 = {8,13,21,32,69};
Arrays.stream(merge(src1,src2)).forEach(s-> System.out.println(s));
}
output:
1
8
13
17
21
32
42
55
69
I need to implement a gnomesort to sort strings on how close they are to the string input. I measure this difference with the Levenshtein-algoritm.
The algoritm works fine but only with if I have two strings in the database. It then sorts it fine, but if there are more than two strings, it just prints them in the order they are in the database. I really can't find the problem
public static void retrieveFromDatabase(String string)
{
String[] sq = new String[database.size()];
database.toArray(sq);
int r = 0, index = 1, y = 2, tmp1 = 0;
String tmp2;
int[] ds = new int[sq.length];
for (int i = 0; i < database.size(); i++) {
ds[i] = sortLevenshtein(string, database.get(i), false);
}
for(index = 1; index < ds.length; index++) // gnomsort
{
if(ds[index - 1] <= ds[index] )
{
++index;
}
else
{
tmp1 = ds[index];
tmp2 = sq[index];
ds[index] = ds[index - 1];
sq[index] = sq[index - 1];
ds[index-1] = tmp1;
sq[index-1] = tmp2;
index--;
if (index == 0)
index++;
}
}
System.out.println("Best matches: ");
for(r=0; r<Math.min(3,sq.length); r++)
{
System.out.println(ds[r] + "\t" + sq[r]);
}
}
The problem
Your gnome sort is not sorting correctly when there are more than two elements to sort.
In your problematic case your ds contains 1, 1, 0 from the outset. In your for loop index is 1. You see that the elements at indices 0 and 1 are in the correct order (both elements are 1), so you increment index to 2 in the if statement. Next your for loop also increments index, so it is now 3. 3 is not less than ds.length (also 3), so the loop terminates.
I don’t know gnome sort, so I can’t tell you the fix. What I can tell you is that manipulating your for loop control variable — index in your code — inside the for loop is the sure way to code that is hard to understand and very hard to find errors in. I never ever do that.
for(index = 1; index < ds.length; index++) // OK: loop control variable is incremented here
{
if(ds[index - 1] <= ds[index] )
{
++index; // No-no: incrementing loop control variable, dangerous
}
else
{
tmp1 = ds[index];
tmp2 = sq[index];
ds[index] = ds[index - 1];
sq[index] = sq[index - 1];
ds[index-1] = tmp1;
sq[index-1] = tmp2;
index--; // No-no: decrementing loop control variable, problematic
if (index == 0)
index++; // No-no: incrementing loop control variable
}
}
I'm trying to solve the problem below from CodeFights. I left my answer in Java after the question. The code works for all the problems, except the last one. Time limit exception is reported. What could I do to make it run below 3000ms (CodeFights requirement)?
Note: Write a solution with O(n) time complexity and O(1) additional space complexity, since this is what you would be asked to do during a real interview.
Given an array a that contains only numbers in the range from 1 to a.length, find the first duplicate number for which the second occurrence has the minimal index. In other words, if there are more than 1 duplicated numbers, return the number for which the second occurrence has a smaller index than the second occurrence of the other number does. If there are no such elements, return -1.
Example
For a = [2, 3, 3, 1, 5, 2], the output should be
firstDuplicate(a) = 3.
There are 2 duplicates: numbers 2 and 3. The second occurrence of 3 has a smaller index than than second occurrence of 2 does, so the answer is 3.
For a = [2, 4, 3, 5, 1], the output should be
firstDuplicate(a) = -1.
Input/Output
[time limit] 3000ms (java)
[input] array.integer a
Guaranteed constraints:
1 ≤ a.length ≤ 105,
1 ≤ a[i] ≤ a.length.
[output] integer
The element in a that occurs in the array more than once and has the minimal index for its second occurrence. If there are no such elements, return -1.
int storedLeastValue = -1;
int indexDistances = Integer.MAX_VALUE;
int indexPosition = Integer.MAX_VALUE;
for (int i = 0; i < a.length; i++)
{
int tempValue = a[i];
for (int j = i+1; j < a.length; j++) {
if(tempValue == a[j])
{
if(Math.abs(i-j) < indexDistances &&
j < indexPosition)
{
storedLeastValue = tempValue;
indexDistances = Math.abs(i-j);
indexPosition = j;
break;
}
}
}
}
return storedLeastValue;
Your solution has two nested for loops which implies O(n^2) while the question explicitly asks for O(n). Since you also have a space restriction you can't use an additional Set (which can provide a simple solution as well).
This question is good for people that have strong algorithms/graph theory background. The solution is sophisticated and includes finding an entry point for a cycle in a directed graph. If you're not familiar with these terms I'd recommend that you'll leave it and move to other questions.
Check this one, it's also O(n) , but without additional array.
int firstDuplicate(int[] a) {
if (a.length <= 1) return -1;
for (int i = 0; i < a.length; i++) {
int pos = Math.abs(a[i]) - 1;
if (a[pos] < 0) return pos + 1;
else a[pos] = -a[pos];
}
return -1;
}
The accepted answer does not work with the task.
It would work if the input array would indeed contain no bigger value than its length.
But it does, eg.: [5,5].
So, we have to define which number is the biggest.
int firstDuplicate(int[] a) {
int size = 0;
for(int i = 0; i < a.length; i++) {
if(a[i] > size) {
size = a[i];
}
}
int[] t = new int[size+1];
for(int i = 0; i < a.length; i++) {
if(t[a[i]] == 0) {
t[a[i]]++;
} else {
return a[i];
}
}
return -1;
}
What about this:
public static void main(String args[]) {
int [] a = new int[] {2, 3, 3, 1, 5, 2};
// Each element of cntarray will hold the number of occurrences of each potential number in the input (cntarray[n] = occurrences of n)
// Default initialization to zero's
int [] cntarray = new int[a.length + 1]; // need +1 in order to prevent index out of bounds errors, cntarray[0] is just an empty element
int min = -1;
for (int i=0;i < a.length ;i++) {
if (cntarray[a[i]] == 0) {
cntarray[a[i]]++;
} else {
min = a[i];
// no need to go further
break;
}
}
System.out.println(min);
}
You can store array values in hashSet. Check if value is already present in hashSet if not present then add it in hashSet else that will be your answer. Below is code which passes all test cases:-
int firstDuplicate(int[] a) {
HashSet<Integer> hashSet = new HashSet<>();
for(int i=0; i<a.length;i++){
if (! hashSet.contains(a[i])) {
hashSet.add(a[i]);
} else {
return a[i];
}
}
return -1;
}
My simple solution with a HashMap
int solution(int[] a) {
HashMap<Integer, Integer> countMap = new HashMap<Integer, Integer>();
int min = -1;
for (int i=0; i < a.length; i++) {
if (!(countMap.containsKey(a[i]))) {
countMap.put(a[i],1);
}
else {
return a[i];
}
}
return min;
}
Solution is very simple:
Create a hashset
keep iterating over the array
if element is already not in the set, add it.
else element will be in the set, then it mean this is minimal index of first/second the duplicate
int solution(int[] a) {
HashSet<Integer> set = new HashSet<>();
for(int i=0; i<a.length; i++){
if(set.contains(a[i])){
// as soon as minimal index duplicate found where first one was already in the set, return it
return a[i];
}
set.add(a[i]);
}
return -1;
}
A good answer for this exercise can be found here - https://forum.thecoders.org/t/an-interesting-coding-problem-in-codefights/163 - Everything is done in-place, and it has O(1) solution.
Problem H (Longest Natural Successors):
Two consecutive integers are natural successors if the second is the successor of the first in the sequence of natural numbers (1 and 2 are natural successors). Write a program that reads a number N followed by N integers, and then prints the length of the longest sequence of consecutive natural successors.
Example:
Input 7 2 3 5 6 7 9 10 Output 3 this is my code so far and i have no idea why it does not work
import java.util.Scanner;
public class Conse {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int x = scan.nextInt();
int[] array = new int[x];
for (int i = 0; i < array.length; i++) {
array[i] = scan.nextInt();
}
System.out.println(array(array));
}
public static int array(int[] array) {
int count = 0, temp = 0;
for (int i = 0; i < array.length; i++) {
count = 0;
for (int j = i, k = i + 1; j < array.length - 1; j++, k++) {
if (Math.abs(array[j] - array[k]) == 1) {
count++;
} else {
if (temp <= count) {
temp = count;
}
break;
}
}
}
return temp + 1;
}
}
Why two loops? What about
public static int array(final int[] array) {
int lastNo = -100;
int maxConsecutiveNumbers = 0;
int currentConsecutiveNumbers = 0;
for (int i = 0; i < array.length; i++) {
if (array[i] == lastNo + 1) {
currentConsecutiveNumbers++;
maxConsecutiveNumbers = Math.max(maxConsecutiveNumbers,
currentConsecutiveNumbers);
} else {
currentConsecutiveNumbers = 1;
}
lastNo = array[i];
}
return Math.max(maxConsecutiveNumbers, currentConsecutiveNumbers);
}
This seems to work:
public static int longestConsecutive(int[] array) {
int longest = 0;
// For each possible start
for (int i = 0; i < array.length; i++) {
// Count consecutive.
for (int j = i + 1; j < array.length; j++) {
// This one consecutive to last?
if (Math.abs(array[j] - array[j - 1]) == 1) {
// Is it longer?
if (j - i > longest) {
// Yup! Remember it.
longest = j - i;
}
} else {
// Start again.
break;
}
}
}
return longest + 1;
}
public void test() {
int[] a = new int[]{7, 2, 3, 5, 6, 7, 9, 10};
System.out.println("Longest: " + Arrays.toString(a) + "=" + longestConsecutive(a));
}
prints
Longest: [7, 2, 3, 5, 6, 7, 9, 10]=3
Since your question has "Problem H" associated with it, I'm assuming you are just learning. Simpler is always better, so it usually pays to break it down into "what has to be done" before starting on a particular road by writing code that approaches the problem with "how can this be done."
In this case, you may be over-complicating things with arrays. A number is a natural successor if it is one greater than the previous number. If this is true, increment the count of the current sequence. If not, we're starting a new sequence. If the current sequence length is greater than the maximum sequence length we've seen, set the max sequence length to the current sequence length. No arrays needed - you only need to compare two numbers (current and last numbers read).
For example:
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int N = scan.nextInt();
int maxSequenceLen = 0; // longest sequence ever
int curSequenceLen = 0; // when starting new sequence, reset to 1 (count the reset #)
int last = 0;
for(int i = 0; i < N; i++) {
int cur = scan.nextInt();
if ((last+1) == cur){
++curSequenceLen;
}
else{
curSequenceLen = 1;
}
if (curSequenceLen > maxSequenceLen){
maxSequenceLen = curSequenceLen;
}
last = cur;
}
System.out.println(maxSequenceLen);
Caveat: I'm answering this on a computer that does not have my Java development environment on it, so the code is untested.
I'm not sure I understand this question correctly. The answer's written here assumes that the the natural successors occur contiguously. But if this is not the same then the solution here might not give the correct answer.
Suppose instead of [7 2 3 5 6 7 9 10] the input was [7 2 6 3 7 5 6 9 10] then the answer becomes 2 while the natural successor [5 6 7] is present in the array.
If the input is not sorted we'll have to use a different approach. Like using HashSet
Load the entire array into a HashSet which removes duplicates.
Pick the first value from the HashSet and assigned it to start and end and remove it from the set.
Now decrements start and check if it is present in the HashSet and continue till a particular value for start is not present int the HashSetwhile removing the value being searched from the set.
Do the same for end except that you will have to increase the value of end for each iteration.
We now have to continuous range from start to end present in the set and whose range is current_Max = end - start + 1
In each iteration we keep track of this current_Max to arrive at the longest natural successor for the entire array.
And since HashSet supports Add, Remove, Update in O(1) time. This algorithm will run in O(n) time, where n is the length of the input array.
The code for this approach in C# can be found here
This is more of an self defined programming exercise than a real problem. I have an array of java.lang.Comparable items. I need to maintain two pointers (an index into the array i.e., int values) i,j . i starts at the beginning of array and moves right until it encounters an element which is less than or equal to the previous element. When it does it stops moving right and ends up pointing to the element which is out of order(element which is not greater than the previous). Similarly j starts at the end of the array and moves left until it finds an element which is not less than the previous.
Also, I need to make sure that the indices don't run out of the array i.e., i cannot go below 0 and j cannot go above arraylength-1
lets say we have an array of 5 elements.
i = 0;
j = 4;(which is the arraylength-1 )
if C,D,E,F,G is the array ,the final values of i and j will be
i = 4 and j = 0
if array is J,D,E,F,G ,the final values of i, j will be
i = 0 , j = 0
if array is B,C,A,D,G , final values of i,j will be
i = 2 , j = 1
I tried to code the logic for moving i to the right, using a while loop as below. I was able to get it working for the i pointer in two cases.
public class PointerMovement{
public static void ptrsPointToOutOfOrderElements(Comparable[] a){
int lo = 0;
int hi = a.length-1;
int i = lo;
int t=i+1;
int j = hi;
//only for moving i to the right .
while(less(a[i],a[t])){
if(t == hi){
i=t;
break;
}
i++;
t++;
}
i=t;
for(Comparable x:a){
System.out.print(x+",");
}
System.out.println();
System.out.println("bad element or end of array at i="+i+"==>"+a[i]);
}
private static boolean less(Comparable x,Comparable y){
return x.compareTo(y) < 0;
}
public static void main(String[] args) {
String[] a = new String[]{"C","D","E","F","G"};//works
//String[] a = new String[]{"B","C","A","D","G"};//works
//String[] a = new String[]{"J","D","E","F","G"};//fails!
ptrsPointToOutOfOrderElements(a);
}
}
My line of reasoning given below
I maintain i=0; and another variable t=i+1
when the while loop fails, less(a[i],a[t]) is false .We need to return a pointer to a[t] which is out of order. so i=t and return i.
if we reach right end of array, the test if(t == hi) passes and we assign i=t and now i points to end of array.
However, the code fails when the out of order element is in the 0th position in the array.
J,D,E,F,G
Instead of i (=0) we get i=1 because i=t is assgined.i ends up pointing to D instead of J.
Can someone point me in the right direction?
update:
this seems to work
public static void ptrsPointToOutOfOrderElements(Comparable[] a){
int lo = 0;
int hi = a.length-1;
int i = lo;
while(less(a[i],a[i+1])){
if(i+1 == hi){
break;
}
i++;
}
i++;
int j = hi;
while(less(a[j-1],a[j])){
if(j-1 == lo){
break;
}
j--;
}
j--;
for(Comparable x:a){
System.out.print(x+",");
}
System.out.println();
if(i>=j){
System.out.println("pointers crossed");
}
System.out.println("bad element or end of array at i="+i+"==>"+a[i]);
System.out.println("bad element or end of array at j="+j+"==>"+a[j]);
}
I do not think you have a problem:
String[] a = new String[]{"C","D","E","F","G"};//works, index should be 4 (but should it be so? It would indicate that G is out of order while it is not. I think you should return 5, indicating that none is out of order.
String[] a = new String[]{"B","C","A","D","G"};//works, index should be 2 as A is out of order
String[] a = new String[]{"J","D","E","F","G"};//works since the first out of order element is indeed D, with index 1
I have tried using simple for loop.
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
for (var i = 0, j = arr.length - 1; i <= j; i++, j--) {
console.log(arr[i] + ' , ' + arr[j]);
}
Output :
1 , 10
2 , 9
3 , 8
4 , 7
5 , 6