sorting using recursion - algorithm

I have the following function to sort an unordered array to having even numbers in the front and odd numbers in the back. Is there a way to get it done without using any loops?
//front is 0, back =array.length-1;
arrangeArray (front, back);
public static void arrangeArray (int front, int back)
{
if (front != back || front<back)
{
while (numbers [front]%2 == 0)
front++;
while (numbers[back]%2!=0)
back--;
if (front < back)
{
int oddnum = numbers [front];
numbers[front]= numbers[back];
numbers[back]=oddnum;
arrangeArray (front+1, back-1);
}
}
}

Mergesort is fairly trivial to code without loops:
void mergesort(int lo, int hi)
{
if (lo<hi)
{
int m=(lo+hi)/2;
mergesort(lo, m);
mergesort(m+1, hi);
merge(lo, m, hi);
}
}
I'll leave making it sort even/odd as an exercise to the reader :)
(Sounds like homework)

When you do recursion, you have a base step and a recursive step.
In this case, the base condition is when front == back, because you start from the edges and end up in the middle. When you get to the middle you know it's done.
Before you do the recursive step, you have to do a bit of sorting. You're only doing the sorting one step at a time, so only deal with the elements at array[front] and array[back] for now. After you arrange those into the right place, do a recursive call.
You'll end up with something like this:
public static void arrangeArray (int front, int back)
{
if(front >= back) return;
int f = numbers[front];
int b = numbers[back];
if(f%2 == 0) {
front++;
} else {
numbers[back] = f;
back--;
}
if (b%2 == 0) {
numbers[front] = b;
front++;
} else {
back--;
}
arrangeArray(front, back);
}
It's untested and probably doesn't work for edge conditions, but it's a good start :)

Wouldn't that simply be:
//front is 0, back =array.length-1;
arrangeArray (front, back);
public static void arrangeArray (int front, int back)
{
if (front != back || front<back)
{
if (numbers [front]%2 == 0)
arrangeArray (front+1, back);
else
if (numbers[back]%2!=0)
arrangeArray (front, back-1);
else
if (front < back)
{
int oddnum = numbers [front];
numbers[front]= numbers[back];
numbers[back]=oddnum;
arrangeArray (front+1, back-1);
}
}
}
?

May I recommend this Python snippet to inspire high level thinking?
compare = lambda x,y: x - y if x%2 == y%2 else y%2 - x%2
>>> sorted([3,4,2,1,5,6,7,90,23,44], cmp=compare)
[1, 3, 5, 7, 23, 2, 4, 6, 44, 90]
I think one needs to build a comparator function that returns negative, 0, and positive and use that.

What you want to do is
arrangeArray(front, back, bool recursed=false) {
if (recursed) {
arrangeArray(front, back/2, true);
return arrangeArray(back/2, back, true);
}
// Do stuff here.
}

The following should be instructive. It's a recursive O(N) solution that rearranges the even numbers in front and odd numbers in the back, but doesn't do any ordering beyond that.
static boolean isEven(int n) {
return (n & 1) == 0;
}
static boolean isOdd(int n) {
return !isEven(n);
}
static int[] swapped(int[] nums, int i, int j) {
int t = nums[i];
nums[i] = nums[j];
nums[j] = t;
return nums;
}
static int[] arrange(int[] nums, int lo, int hi) {
return
(lo >= hi) ? nums :
(isEven(nums[lo])) ? arrange(nums, lo + 1, hi) :
(isOdd(nums[hi])) ? arrange(nums, lo, hi - 1) :
arrange(swapped(nums, lo, hi), lo + 1, hi - 1);
}
static void evenOddSort(int... nums) {
System.out.println(java.util.Arrays.toString(
arrange(nums, 0, nums.length - 1)
));
}
public static void main(String[] args) {
evenOddSort(1,3,5,7,2,4,6);
} // prints "[6, 4, 2, 7, 5, 3, 1]"
I think the ternary operator makes the recursion flow more naturally, but if you're not that comfortable with how it works, you can just use traditional if-else.
static int[] arrange(int[] nums, int lo, int hi) {
if (lo >= hi) {
return nums;
} else if (isEven(nums[lo])) {
return arrange(nums, lo + 1, hi);
} else if (isOdd(nums[hi])) {
return arrange(nums, lo, hi - 1);
} else {
return arrange(swapped(nums, lo, hi), lo + 1, hi - 1);
}
}

Related

How to add memoization in subset sum?

I am trying to solve subset sum problem with recursive solution, but to make to make it a bit more efficient I am trying to put memoization in it. However the code without memoization gives correct solution but with memoization it doesn't work properly.
public int subsetSum(int num[], int idx, int expecedSum, int dp[]) {
if (expecedSum == 0) {
return 1;
}
else if (idx < 0 || expecedSum < 0) {
return 0;
}
else {
if (dp[expecedSum] == -1) {
int x = subsetSum(num, idx - 1, expecedSum, dp);
int y = subsetSum(num, idx - 1, expecedSum - num[idx], dp);
dp[expecedSum] = (x == 1 || y == 1) ? 1 : 0;
}
return dp[expecedSum];
}
}
public static void main(String args[]) {
Solution s = new Solution();
int num[] = new int[]{1, 2, 3, 4, 5, 6, 7};
int sum = 0;
int n = new Scanner(System.in).nextInt();
int dp[] = new int[n + 1];
for (int i = 0; i < dp.length; i++) {
dp[i] = -1;
}
dp[0] = 1;
s.subsetSum(num, num.length - 1, n, dp);
}
Can someone help me with why this is not working?
If I enter n = 14 then ideally dp[14] should contains 1 but it doesn't contain 1.
The sum is not sufficient to describe the state. The pair (sum, index) is. If you make dp an array of arrays of size (max_sum + 1) x num.length and apply memoization for a pair (idx, expectedSum) in the subsetSet method, it works.
It has been years but this may help someone today.
The idea is to take both the state - means once with including current element into the sum and once excluding current element into the sum. and then taking OR(||) for those values and store in the cache.
the code will look something like this -
#include <iostream>
#include <vector>
using namespace std;
bool sumExists(vector<int> & a, int cursum, int n, vector<vector<int>> &dp) {
if(n==0 && cursum != 0)
return 0;
if(cursum==0)
return 1;
if(dp[n][cursum] != -1) {
return dp[n][cursum];
}
int newsum = cursum - a[n-1];
bool returnval = false;
if(newsum>=0) {
dp[n][newsum] = sumExists(a, newsum, n-1, dp);
dp[n][cursum] = sumExists(a, cursum, n-1, dp);
returnval = dp[n][newsum] || dp[n][cursum];
} else {
dp[n][cursum] = sumExists(a, cursum, n-1, dp);
returnval = dp[n][cursum];
}
return returnval;
}
int main() {
// your code goes here
vector<int> a{2,0,7,8,10};
int n = a.size();
int sum = 11;
vector<vector<int>> dp(n+1, vector<int>(sum+1, -1));
for(int i=0;i<=n;++i) {
dp[i][0]=true;
}
for(int i=1;i<=sum;++i) {
dp[0][i]=false;
}
if(sumExists(a, sum, n, dp)) {
cout<<"YES"<<endl;
} else {
cout<<"NO"<<endl;
}
}

DP memoized approach for Longest common substring

can anyone provide the memoized approach for longest common substring between two strings.I know the bottom solution but I am not able to think in top-down manner.
Expected time complexity-O(n^2)
TOP-DOWN APPROACH
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
string X, Y; //input strings
int ans, dp[105][105]; // ans : answer
int LCS(int n, int m) //our function return value of (n,m) state
{ // so that we can use the result in (n+1,m+1) state
if(n == 0 || m == 0) return 0; //in case of match in (n+1,m+1) state
if(dp[n][m] != -1) return dp[n][m];
LCS(n-1,m); //to visit all n*m states (try example: X:ASDF
LCS(n,m-1); // we call these states first Y:ASDFF)
if(X[n-1] == Y[m-1])
{
dp[n][m] = LCS(n-1,m-1) + 1;
ans = max(ans, dp[n][m]);
return dp[n][m];
}
return dp[n][m] = 0;
}
int main()
{
int t; cin>>t;
while(t--)
{
int n, m; cin>>n>>m; //length of strings
cin>>X>>Y;
memset(dp, -1, sizeof dp);
ans = 0;
LCS(n, m);
cout<<ans<<'\n';
}
return 0;
}
Memoization with recursion works with top-down approach.
Taking LCS example using DP from Cormen into consideration below is the pseudo code describing how it will work.
MEMOIZED-LCS-LENGTH(X,Y)
m<-length[X]
n<-length[Y]
for(i<-1 to m)
do for(j<-1 to n)
c[i,j]<- -1
for(i<-1 to m)
c[i,0]<-0
for(j<-1 to n)
c[0,j]<-0
return RECURSIVE-LCS-LENGTH(X,Y,1,1)
RECURSIVE-LCS-LENGTH(X,Y,i,j)
if(c[i,j]!=-1)
return c[i,j]
//Above 2 line fetches the result if already present, instead of computing it again.
if(x[i]==y[j])
then c[i,j]<-RECURSIVE-LCS-LENGTH(X,Y,i+1,j+1)+1
else
c1<- RECURSIVE-LCS-LENGTH(X,Y,i+1,j)
c2<-RECURSIVE-LCS-LENGTH(X,Y,i,j+1)
if(c1<c2)
then c[i,j]<-c1
else c[i,j]<-c2
return c[i,j]
Java Solution:
class Solution {
public int findLength(int[] A, int[] B) {
int[][] cache = new int[A.length][B.length];
Arrays.stream(cache).forEach(a->Arrays.fill(a,-1));
int[] res = new int[1];
findLength(0, 0, A, B, cache, res);
return res[0];
}
public static int findLength(int a, int b, int[] A, int[] B, int[][] cache, int[] res){
if( a >= A.length || b >= B.length )
return 0;
if(cache[a][b] != -1){
return cache[a][b];
}
if(A[a] == B[b]){
cache[a][b] = 1 + findLength(a+1,b+1,A,B,cache,res);
// remember you can not return here: why? see case: s1 = 1,2,3 s2=1,4,1,2,3
}
// try out other possiblities and update cache
findLength(a+1,b,A,B,cache,res);
findLength(a,b+1,A,B,cache,res);
//you can avoid this and find max value at end in cache
res[0] = Math.max(res[0],cache[a][b]);
//at this point cache might have -1 or updated value, if its -1 make it to 0 as this location is visited and no common substring is there from here
cache[a][b] = Math.max(0,cache[a][b]);
return cache[a][b];
}
}
Recursion plus memoization in python. Please note this code is partially accepted on Hackerearth and Geeksforgeeks.For larger test cases, it is giving MLE.
import sys
sys.setrecursionlimit(1000000)
maxlen=0
t=None
def solve(s1, s2, n, m):
global maxlen, t
if n<=0 or m<=0:
return 0
if t[n][m]!=-1:
return t[n][m]
if s1[n-1]==s2[m-1]:
temp=1+solve(s1, s2, n-1, m-1)
maxlen=max(maxlen, temp)
t[n][m]=temp
return temp
t[n][m]=0
return 0
class Solution:
def longestCommonSubstr(self, S1, S2, n, m):
global maxlen, t
maxlen=0
t=[[-1]*(m+1) for i in range(n+1)]
for i in range(n+1):
for j in range(m+1):
solve(S1, S2, i, j)
return maxlen
if __name__=='__main__':
S1=input().strip()
S2=input().strip()
n=len(S1)
m=len(S2)
ob = Solution()
print(ob.longestCommonSubstr(S1, S2, n, m))
An easy solution is described below. Here memo[n][m] does not store the length of
greatest substring but you can store the greatest substring in pointer maxi as follows:
#include<iostream>
#include<string>
using namespace std;
int lcs(string X,string Y,int n,int m,int *maxi,int memo[][8]) {
if(n==0||m==0) {
return 0;
}
int k=0;
int j=0;
if(memo[n-1][m-1]!=-1) {
return memo[n-1][m-1];
}
if(X[n-1]==Y[m-1]) {
memo[n-1][m-1] = 1+lcs(X,Y,n-1,m-1,maxi,memo);
if(*maxi<memo[n-1][m-1])
*maxi=memo[n-1][m-1];
}
else {
memo[n-1][m-1]=0;
}
int l = lcs(X,Y,n-1,m,maxi,memo);
int i = lcs(X,Y,n,m-1,maxi,memo);
return memo[n-1][m-1];
}
int main()
{
int n,m;
string X = "abcdxyze";
//string X = "abcd";
string Y = "xyzabcde";
n=X.length();
m=Y.length();
int memo[n][8];
for(int i=0;i<n;i++) {
for(int j=0;j<m;j++) {
memo[i][j]=-1;
}
}
int maxi=0;
int k = lcs(X,Y,n,m,&maxi,memo);
cout << maxi;
return 0;
}
class Solution {
public:
int t[1005][1005];
int maxC = 0;
int recur_memo(vector<int>& nums1, vector<int>& nums2, int m, int n) {
if(t[m][n] != -1)
return t[m][n];
if(m == 0 || n == 0)
return 0;
int max_substring_ending_here = 0;
//Example : "abcdezf" "abcdelf"
//You see that wowww, string1[m-1] = string2[n-1] = 'f' and you happily
go for (m-1, n-1)
//But you see, in future after a gap of 'l' and 'z', you will find
"abcde" and "abcde"
if(nums1[m-1] == nums2[n-1]) {
max_substring_ending_here = 1 + recur_memo(nums1, nums2, m-1, n-1);
}
//May be you find better results if you do (m-1, n) and you end up
updating maxC with some LAAARGEST COMMON SUBSTRING LENGTH
int decrease_m = recur_memo(nums1, nums2, m-1, n); //stage (m-1, n)
//OR,
//May be you find better results if you do (m, n-1) and you end up
updating maxC with some LAAARGEST COMMON SUBSTRING LENGTH
int decrease_n = recur_memo(nums1, nums2, m, n-1); //stage (m, n-1)
//Like I said, you need to keep on finding the maxC in every call you
make throughout your journey.
maxC = max({maxC, max_substring_ending_here, decrease_m, decrease_n});
//BUT BUT BUT, you need to return the best you found at this stage (m, n)
return t[m][n] = max_substring_ending_here;
}
int findLength(vector<int>& nums1, vector<int>& nums2) {
int m = nums1.size();
int n = nums2.size();
memset(t, -1, sizeof(t));
recur_memo(nums1, nums2, m, n); //resurive+memoization
return maxC;
}
};
Link : https://leetcode.com/problems/maximum-length-of-repeated-subarray/discuss/1169215/(1)-Recursive%2BMemo-(2)-Bottom-Up-(C%2B%2B)
Here is a recursive and top-down approach:
public int lcsSubstr(char[] s1, char[] s2, int m, int n, int c) {
if (m == 0 || n == 0) {
return c;
}
if (s1[m-1] == s2[n-1]) {
c = lcsSubstr(s1, s2, m-1, n-1, c+1);
} else {
c2 = Math.max(lcsSubstr(s1, s2, m, n - 1, 0), lcsSubstr(s1, s2, m-1, n, 0));
}
return Math.max(c, c2);
}
public int lcsSubstrMemo(char[] s1, char[] s2, int m, int n, int c, int[][] t) {
if(m == 0 || n == 0) {
return c;
}
if (t[m-1][n-1] != -1) return t[m-1][n-1];
if(s1[m - 1] == s2[n - 1]) {
c = lcsSubstr(s1, s2, m - 1, n - 1, c + 1);
} else {
c2 = Math.max(lcsSubstr(s1, s2, m, n - 1, 0), lcsSubstr(s1, s2, m - 1, n, 0));
}
t[m - 1][n - 1] = Math.max(c, c2);
return t[m-1][n-1];
}
Memoization refers to caching the solutions to subproblems in order to use them later. In the longest common subsequence problem, you try to match substrings of two subsequences to see if they match, maintaining in memory the longest one yet found. Here is the solution in Java you are looking for (memoized version of LCS):
public class LongestCommonSubsequence {
private static HashMap<Container, Integer> cache = new HashMap<>();
private static int count=0, total=0;
public static void main(String sargs[]){
Scanner scanner = new Scanner(System.in);
String x=scanner.nextLine();
String y=scanner.nextLine();
int max=0;
String longest="";
for(int j=0;j<x.length();j++){
String common=commonSubsequence(j,0, x, y);
if(max<common.length()){
max=common.length();
longest=common;
}
}
for(int j=0;j<y.length();j++){
String common=commonSubsequence(j,0, y, x);
if(max<common.length()){
max=common.length();
longest=common;
}
}
System.out.println(longest);
System.out.println("cache used "+count+" / "+total);
}
public static String commonSubsequence(final int startPositionX, int startPositionY, String x, String y){
StringBuilder commonSubsequence= new StringBuilder();
for(int i=startPositionX;i<x.length();i++){
Integer index=find(x.charAt(i),startPositionY,y);
if(index!=null){
commonSubsequence.append(x.charAt(i));
if(index!=y.length()-1)
startPositionY=index+1;
else
break;
}
}
return commonSubsequence.toString();
}
public static Integer find(char query, int startIndex, String target){
Integer pos=cache.get(new Container(query, startIndex));
total++;
if(pos!=null){
count++;
return pos;
}else{
for(int i=startIndex;i<target.length();i++){
if(target.charAt(i)==query){
cache.put(new Container(query, startIndex), i);
return i;
}
}
return null;
}
}
}
class Container{
private Character toMatch;
private Integer indexToStartMatch;
public Container(char t, int i){
toMatch=t;
indexToStartMatch=i;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime
* result
+ ((indexToStartMatch == null) ? 0 : indexToStartMatch
.hashCode());
result = prime * result + ((toMatch == null) ? 0 : toMatch.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Container other = (Container) obj;
if (indexToStartMatch == null) {
if (other.indexToStartMatch != null)
return false;
} else if (!indexToStartMatch.equals(other.indexToStartMatch))
return false;
if (toMatch == null) {
if (other.toMatch != null)
return false;
} else if (!toMatch.equals(other.toMatch))
return false;
return true;
}
}

Find smallest number in Sorted Rotatable Array

I came across this question in one Interview. Please help me in getting the solution.
Question is:
You have sorted rotatable array, i. e. the array contains elements which are sorted and it can be rotated circularly, like if the elements in array are [5,6,10,19,20,29] then rotating first time array becomes [29,5,6,10,19,20] and on second time it becomes [20,29,5,6,10,19] and so on.
So you need to find the smallest element in the array at any point. You won’t be provided with number times array is rotated. Just given the rotated array elements and find out the smallest among them. In this case output should be 5.
Method 1:
You can do this in O(logN) time.
Use a modified binary search to find the point of rotation which is an index i such that arr[i] > arr[i+1].
Example:
[6,7,8,9,1,2,3,4,5]
^
i
The two sub-arrays (arr[1], arr[2], .., arr[i]) and (arr[i+1], arr[i+2], ..., arr[n]) are sorted.
The answer is min(arr[1], arr[i+1])
Method 2:
When you split the sorted, rotated array into two halves (arr[1],..,arr[mid]) and (arr[mid+1],..,arr[n]), one of them is always sorted and the other always has the min. We can directly use a modified binary search to keep searching in the unsorted half
// index of first element
l = 0
// index of last element.
h = arr.length - 1
// always restrict the search to the unsorted
// sub-array. The min is always there.
while (arr[l] > arr[h]) {
// find mid.
mid = (l + h)/2
// decide which sub-array to continue with.
if (arr[mid] > arr[h]) {
l = mid + 1
} else {
h = mid
}
}
// answer
return arr[l]
The above algorihtm fails if data element is repeated like {8,8,8,8,8} or {1,8,8,8,8} or {8,1,8,8,8} or {8,8,1,8,8} or {8,8,8,8,1}
// solution pasted below will work all test cases :)
//break the array in two subarray and search for pattern like a[mid]>a[mid+1]
// and return the min position
public static int smallestSearch(int[] array,int start,int end)
{
if(start==end)
return array.length;
int mid=(start+end)/2;
if(array[mid]>array[mid+1])
return min(mid+1,smallestSearch(array,start,mid),smallestSearch(array,mid+1,end));
else
return min(smallestSearch(array,start,mid),smallestSearch(array,mid+1,end));
}
public static int min(int a,int b)
{
if(a==b)
return a;
else if(a<b)
return a;
else
return b;
}
public static int min(int a,int b,int c)
{
if(a<c)
{
if(a<b)
{
return a;
}
else
{
return b;
}
}
else
{
if(b<c)
return b;
else
return c;
}
}
To Find the smallest number in the sorted rotated array:
using Binary search concept
public class RotatedSortedArrayWithoutDuplicates1 {
public static void main(String[] args) {
int[] a = { 4, 6, 8, 10, 34, 56, 78, 1, 3 };
System.out.println(findMin(a));
}
private static int findMin(int[] a) {
if (a.length == 0 || a == null) {
return -1;
}
int start = 0;
int last = a.length - 1;
while (start + 1 < last) {
int mid = start + (last - start) / 2;
int m = a[mid];
int s = a[start];
int l = a[last];
if (m > l) {
start = mid + 1;
}
if (m < l) {
last = mid;
} else {
last--;
}
} // while
if (a[start] > a[last]) {
return a[last];
} else {
return a[start];
}
}
}
But if you don't want to use Binary Search, then :
public class Abc {
public static void main(String[] args) {
int[] a = { 4, 5, 6, 7, 7, 8, 9, 1, 1, 2, 3, 3 };
System.out.println(findMin(a));
}
public static int findMin(int[] a) {
int min = a[a.length - 1];
for (int i = 0; i < a.length; i++) {
if (min > a[i]) {
min = a[i];
break;
}
}
return min;
}// findmin
}// end
Here is the code in Python:
def fix(a):
min = a[0]
for i in range(len(a)):
if(min > a[i]):
min = a[i]
break
return min
a = [2, 2,3,4,1,2]
print(fix(a))
My code is below with the algorithm as comments. Works even for the repeated elements.
//Find Min in Rotated Sorted Array
//Example: int array[10] = {7, 8, 9, 10, 11, 12, 3, 4, 5, 6};
// Min in the above array is 3
// Solution: Recursively search (Modified binary search) for the Pivot where is the smallest Element is present
// Algorithm:
// 1) Find the Mid of the Array
// 2) call the recursive function on segment of array in which there is a deviation in the order
// If (A[low] > A[mid]) array segment in which deviation in the order present is (low, mid)
// If (A[low] < A[mid]) array segment in which deviation in the order present is (mid + 1, high)
// Time Complexity: O(logn)
// Space Complexity: is of the recursive function stack that is being used
#define MIN(x,y) (x) <= (y) ? (x): (y)
int MininRotatedSortedArray(int A[], int low, int high)
{
if(low > high)
return -1;
if(low == high - 1)
return MIN(A[low], A[high]);
int mid = low + (high - low)/2;
if(A[low] > A[mid])
return MininRotatedSortedArray(A, low, mid);
else if(A[low] < A[mid])
return MininRotatedSortedArray(A, mid + 1, high);
else
return A[mid];
}
This can be done in O(1) time best case, O(n) time worst case, and O(lg n) time on average.
For a rotated sorted array, if the first element in the array is less than the last element in the array, then the sorted array is not rotated (or rotated 0 position). The minimum element is simply the first element.
If the middle element is less than the last element, then the minimum element is in [first, middle].
If the middle element is greater than the last element, then the minimum element is in [middle + 1, last].
If the middle element is equal to the last element, then there are two sub-cases:
the first element is larger than the last element, in which case the minimum element is in [first, middle + 1];
the first element is equal to the last element, in which case it is inconclusive to reject either half of the array. Reduce to linear search. For example, for arrays such as [5,5,5,1,5] and [5,1,5,5,5], it is impossible by just examining the first, last and middle element (since they are all equal) which half of the array the minimum element lies.
I wrote the following code in C++ to solve this problem, which should handle all cases (empty array, repeated elements).
template <typename Iterator>
Iterator rotated_min(Iterator begin, Iterator end)
{
while (begin != end)
{
if (*begin < *(end - 1))
{
return begin;
}
Iterator mid = begin + (end - 1 - begin) / 2;
if (*mid < *(end - 1))
{
end = mid + 1;
}
else if (*mid > *(end - 1))
{
begin = mid + 1;
}
else
{
if (*begin > *(end - 1))
{
end = mid + 1;
++begin;
}
else
{
//reduce to linear search
typename ::std::iterator_traits<Iterator>::value_type min_value = *begin;
Iterator min_element = begin;
for (Iterator i = begin + 1; i != end; ++i)
{
if (*i < min_value)
{
min_value = *i;
min_element = i;
}
}
return min_element;
}
}
}
return begin;
}
Find Min index in circular sorted array
Example : [7,8,9,1,2,3,4,5,6]
int findMinIndex(int []a, int start, int end)
{
int mid = (start + end)/2;
if (start - end == 1)
if(a[start] < a[end])
return start;
else
return end;
if (a[mid] > a[end]){
return findMinIndex(a,mid,end);
}
else{
return findMinIndex(a,start,mid);
}
return -1; //Not found
}
In case any one needs it.. My implementation in java..
takes care of sorted/unsorted ascending//descending order usecases..
drawback is it will still perform log n steps to find min value in a perfectly sorted set with no rotation.
http://ideone.com/fork/G3zMIb
/* package whatever; // don't place package name! */
import java.util.*;
import java.lang.*;
import java.io.*;
/* Name of the class has to be "Main" only if the class is public. */
class Ideone
{
public static void main (String[] args) throws java.lang.Exception
{
int [] a = {3,3,0,2,2,2,2,1,2,2,2,2,2,2,2,2,2};
System.out.println(recursiveSplit(a,0,a.length-1));
}
public static int findMin(int x, int y){
if(x<=y){
return x;
}else{
return y;
}
}
public static int recursiveSplit(int[] arr , int a , int b){
int mid = (int) Math.floor(a + (b-a)/2);
int h1_l = a;
int h1_u = mid;
int h2_l = mid+1;
int h2_u = b;
int x=0;
int y=0;
//single element
if(a==b){
return arr[a];
}
//adjacent positions
if(h1_u-h1_l==1){
x=findMin(arr[h1_u],arr[h1_l]);
}else{
//else split
x=recursiveSplit(arr,h1_l,h1_u);
}
if(h2_u-h2_l==1){
y=findMin(arr[h2_u],arr[h2_l]);
}else{
y=recursiveSplit(arr, h2_l,h2_u);
}
return findMin(x, y);
}
}
Errors/suggestions/failed usecases are welcomed
public int findMin(int[] num) {
return findMin(num, 0, num.length-1);
}
public int findMin(int[] num, int left, int right){
if(left==right) return num[left];
if(left+1==right) return Math.min(num[left], num[right]);
int mid = (left+right)/2;
if(num[mid]>num[right]){
return findMin(num,mid+1,right);
}else if(num[mid]<num[right]){
return findMin(num,left,mid);
}else{
if(num[mid]==num[left]){
return Math.min(findMin(num,left,mid), findMin(num,mid,right));
}else{
return findMin(num,left,mid);
}
}
}
The following algorithm takes log(n) time. Assuming the array has no duplicate.
public int findMin(int[] num) {
if(num.length == 0) return -1
int r = num.length-1, l = 0;
while(l<r){
if(num[l]<=num[r]) return num[l]; //when not rotated, return the left most value
int mid = (r+l)/2;
if(num[mid]<num[r]){
r = mid;
}else{
l = mid+1;
}
}
return num[l];
}
I did it using a slightly modified version of binary search. What I am doing here is I keep going left or right based on where the minimum could be. For example in an ascending array if the mid element is less than the left most element, its possible that the minimum is to the left. While recursing thru the array, I also keep track of the minimum. The recursion continues until the end and then the latest min is returned. This also works with repeated elements.
public static void main(String[] args) throws IOException {
int[] rotated = {6, 7, 8, 1, 2, 3, 4, 5};
int min = findMin(rotated);
System.out.println(min);//1
}
public static int findMin(int[] sorted) {
return findMinRecursively(sorted, sorted[0], 0, (sorted.length - 1));
}
private static int findMinRecursively(int[] sorted, int min, int leftIndex, int rightIndex) {
if (leftIndex > rightIndex) {
return min;
}
int midIndex = (leftIndex + rightIndex) / 2;
if (sorted[midIndex] < min) {
min = sorted[midIndex];
}
if (sorted[midIndex] < sorted[leftIndex]) {
return findMinRecursively(sorted, min, leftIndex, (midIndex - 1));
} else {
return findMinRecursively(sorted, min, (midIndex + 1), rightIndex);
}
}
Question : Find minimum in a sorted rotated array .
Solution 1 : Using Binary Search
class Test18 {
public static void main(String[] args) {
int[] a = { 5, 6, 7, 8, 9, 10, 1, 2, 3 };
System.out.println(findmin(a));
}
// find min in a sorted rotated array
private static int findmin(int[] a) {
int start = 0;
int last = a.length - 1;
while (start + 1 < last) {
int mid = start + (last - start) / 2;
if (a[mid] > a[last]) {
start = mid + 1;
}
if (a[mid] < a[last]) {
last = mid;
} else {
mid--;
}
} // while
if (a[start] > a[last]) {
return a[last];
} else {
return a[start];
}
}
}
def searchinrotatedarray(arr1,l,h):
if l>h:
return arr1[0]
if h==l:
return arr1[l]
mid=(l+h)//2
if mid<h and arr1[mid+1]<arr1[mid]:
return arr1[mid+1]
elif mid>l and arr1[mid-1]<arr1[mid]:
return arr1[mid]
elif arr1[mid]<arr1[h]:
return searchinrotatedarray(arr1,l,mid-1)
else:
return searchinrotatedarray(arr1,mid+1,h)
first if statement checks if even array is rotated at all. in that case first element is the min . if length of list is 1 then that element is min.
else if mid element is less than last element then continue to look in second half else look for the element in first half
//java program to find minimum element in a sorted array rotated
//about any pivot in O(log n) in worst case and O(1) in best case
class ArrayRotateMinimum {
public static void main(String str[]) {
// initialize with your sorted rotated array here
int array[] = { 9, 1, 2, 3, 4, 5, 6, 7, 8, };
System.out.println("Minimum element is: " + minimumElement(array));
}
static int minimumElement(int array[]) {
// variables to keep track of low and high indices
int low, mid, high;
// initializing variables with appropriate values
low = 0;
high = array.length - 1;
while (low < high) {
// mid is always defined to be the average of low and high
mid = (low + high) / 2;
if (array[low] > array[mid]) {
// for eg if array is of the form [9,1,2,4,5],
// then shift high to mid to reduce array size by half
// while keeping minimum element between low and high
high = mid;
} else if (array[mid] > array[high]) {
// this condition deals with the end case when the final two
// elements in the array are of the form [9,1] during the
// last iteration of the while loop
if (low == mid) {
return array[high];
}
// for eg if array is of the form [4,5,9,1,2],
// then shift low to mid to reduce array size by half
// while keeping minimum element between low and high
low = mid;
} else {
// the array has not been rotated at all
// hence the first element happens to be the smallest element
return array[low];
}
}
//return first element in case array size is just 1
return array[0];
}
}
This is my pythonic solution using recursion:
Time complexity is O(log(n)) & Space complexity: O(1)
class Solution(object):
def findMin(self, nums):
left = 0
right = len(nums) -1
mid = len(nums) // 2
if len(nums) == 0:
return -1
if len(nums) == 1:
return nums[left]
if len(nums) == 2:
return min(nums[left], nums[right])
if nums[left] < nums[right]:
return nums[left]
elif nums[mid] > nums[left]:
return self.findMin(nums[mid + 1: ])
elif nums[mid] < nums[left]:
return self.findMin(nums[: mid + 1])
Here is a very simple answer, it will work for all test cases:
int a[] = {5,6,7,1,2,3,4};
int a[] = {1,2,3};
int a[] = {3,2,1};
int a[] = {3,1,2};
int a[] = {2,2,2,2};
public class FindSmallestNumberInSortedRotatedArray {
public static void main(String[] args) {
int a[] = { 4, 5, 6, 7, 1, 2, 3 };
int j = a.length - 1;
int i = 0;
while (i < j) {
int m = (i + j) / 2;
if (a[m] < a[m + 1] && a[m] < a[m - 1]) {
System.out.println(a[m] + "is smallest element ");
break;
} else if (a[m] > a[m + 1] && a[m - 1] > a[m + 1]) {
i = m + 1;
} else {
j = m - 1;
}
}
if (i == j)
System.out.println(a[i] + " is smallest element");
}
Solution for both array with duplicate and not, with the recursive binary search approach.
Unique array
var min = (A, l, h) => {
if(l >= h) return A[l];
let m = Math.floor((l + h) / 2);
// as its unique
if(A[m] > A[h]) {
// go towards right as last item is small than mid
return min(A, m + 1, h);
} else if(A[m] > A[m - 1]) {
// go towards left as prev item is smaller than current
return min(A, l, m - 1);
} else {
// right and left is greater than current
return A[m];
}
}
/**
* #param {number[]} nums
* #return {number}
*/
var findMin = function(nums) {
// If array is rotated nums.length time or same as it is
if(nums[0] < nums[nums.length - 1]) return nums[0];
return min(nums, 0, nums.length - 1);
};
Array with duplicates
var min = (A, l, h) => {
if(l >= h) return A[l];
// traverse from left "and right" to avoid duplicates in the end
while(A[l] == A[l+1]) {
l++;
}
let m = Math.floor((l + h) / 2);
// as its unique
if(A[m] > A[h]) {
// go towards right as last item is small than mid
return min(A, m + 1, h);
} else if(A[m] >= A[m - 1]) {
// go towards left as prev item is smaller than current
return min(A, l, m - 1);
} else {
// right and left is greater than current
return A[m];
}
}
/**
* #param {number[]} nums
* #return {number}
*/
var findMin = function(nums) {
// If array is rotated nums.length time or same as it is
if(nums[0] < nums[nums.length - 1]) return nums[0];
return min(nums, 0, nums.length - 1);
};

what is the fastest way to find the gcd of n numbers?

what is the fastest way to compute the greatest common divisor of n numbers?
Without recursion:
int result = numbers[0];
for(int i = 1; i < numbers.length; i++){
result = gcd(result, numbers[i]);
}
return result;
For very large arrays, it might be faster to use the fork-join pattern, where you split your array and calculate gcds in parallel. Here is some pseudocode:
int calculateGCD(int[] numbers){
if(numbers.length <= 2){
return gcd(numbers);
}
else {
INVOKE-IN-PARALLEL {
left = calculateGCD(extractLeftHalf(numbers));
right = calculateGCD(extractRightHalf(numbers));
}
return gcd(left,right);
}
}
You may want to sort the numbers first and compute the gcd recursively starting from the smallest two numbers.
C++17
I have written this function for calculating gcd of n numbers by using C++'s inbuilt __gcd(int a, int b) function.
int gcd(vector<int> vec, int vsize)
{
int gcd = vec[0];
for (int i = 1; i < vsize; i++)
{
gcd = __gcd(gcd, vec[i]);
}
return gcd;
}
To know more about this function visit this link .
Also refer to Dijkstra's GCD algorithm from the following link. It works without division. So it could be slightly faster (Please correct me if I am wrong.)
You should use Lehmer's GCD algorithm.
How about the following using Euclidean algorithm by subtraction:
function getGCD(arr){
let min = Math.min(...arr);
let max= Math.max(...arr);
if(min==max){
return min;
}else{
for(let i in arr){
if(arr[i]>min){
arr[i]=arr[i]-min;
}
}
return getGCD(arr);
}
}
console.log(getGCD([2,3,4,5,6]))
The above implementation takes O(n^2) time. There are improvements that can be implemented but I didn't get around trying these out for n numbers.
If you have a lot of small numbers, factorization may be actually faster.
//Java
int[] array = {60, 90, 45};
int gcd = 1;
outer: for (int d = 2; true; d += 1 + (d % 2)) {
boolean any = false;
do {
boolean all = true;
any = false;
boolean ready = true;
for (int i = 0; i < array.length; i++) {
ready &= (array[i] == 1);
if (array[i] % d == 0) {
any = true;
array[i] /= d;
} else all = false;
}
if (all) gcd *= d;
if (ready) break outer;
} while (any);
}
System.out.println(gcd);
(works for some examples, but not really tested)
Use the Euclidean algorithm :
function gcd(a, b)
while b ≠ 0
t := b;
b := a mod b;
a := t;
return a;
You apply it for the first two numbers, then the result with the third number, etc... :
read(a);
read(b);
result := gcd(a, b);
i := 3;
while(i <= n){
read(a)
result := gcd(result, a);
}
print(result);
Here below is the source code of the C program to find HCF of N numbers using Arrays.
#include<stdio.h>
int main()
{
int n,i,gcd;
printf("Enter how many no.s u want to find gcd : ");
scanf("%d",&n);
int arr[n];
printf("\nEnter your numbers below :- \n ");
for(i=0;i<n;i++)
{
printf("\nEnter your %d number = ",i+1);
scanf("%d",&arr[i]);
}
gcd=arr[0];
int j=1;
while(j<n)
{
if(arr[j]%gcd==0)
{
j++;
}
else
{
gcd=arr[j]%gcd;
i++;
}
}
printf("\nGCD of k no.s = %d ",gcd);
return 0;
}
For more refer to this website for further clarification.......
You can use divide and conquer. To calculate gcdN([]), you divide the list into first half and second half. if it only has one num for each list. you calculate using gcd2(n1, n2).
I just wrote a quick sample code. (assuming all num in the list are positive Ints)
def gcdN(nums):
n = len(nums)
if n == 0: return "ERROR"
if n == 1: return nums[0]
if n >= 2: return gcd2(gcdN(nums[:n//2]), gcdN(nums[n//2:]))
def gcd2(n1, n2):
for num in xrange(min(n1, n2), 0, -1):
if n1 % num == 0 and n2 % num == 0:
return num
Here's a gcd method that uses the property that gcd(a, b, c) = gcd(a, gcd(b, c)).
It uses BigInteger's gcd method since it is already optimized.
public static BigInteger gcd(BigInteger[] parts){
BigInteger gcd = parts[0];
for(int i = 1; i < parts.length; i++)
gcd = parts[i].gcd(gcd);
return gcd;
}
//Recursive solution to get the GCD of Two Numbers
long long int gcd(long long int a,long long int b)<br>
{
return b==0 ? a : gcd(b,a%b);
}
int main(){
long long int a,b;
cin>>a>>b;
if(a>b) cout<<gcd(a,b);
else cout<<gcd(b,a);
return 0;
}
import java.io.*;
import java.util.*;
import java.text.*;
import java.math.*;
import java.util.regex.*;
class GCDArray{
public static int [] extractLeftHalf(int [] numbers)
{
int l =numbers.length/2;
int arr[] = Arrays.copyOf(numbers, l+1);
return arr;
}
public static int [] extractRightHalf(int [] numbers)
{
int l =numbers.length/2;
int arr[] = Arrays.copyOfRange(numbers,l+1, numbers.length);
return arr;
}
public static int gcd(int[] numbers)
{
if(numbers.length==1)
return numbers[0];
else {
int x = numbers[0];
int y = numbers[1];
while(y%x!=0)
{
int rem = y%x;
y = x;
x = rem;
}
return x;
}
}
public static int gcd(int x,int y)
{
while(y%x!=0)
{
int rem = y%x;
y = x;
x = rem;
}
return x;
}
public static int calculateGCD(int[] numbers){
if(numbers.length <= 2){
return gcd(numbers);
}
else {
int left = calculateGCD(extractLeftHalf(numbers));
int right = calculateGCD(extractRightHalf(numbers));
return gcd(left,right);
}
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int arr[] = new int[n];
for(int i=0;i<n;i++){
arr[i]=sc.nextInt();
}
System.out.println(calculateGCD(arr));
}
}
**
Above is the java working code ..... the pseudo code of which is
already mention by https://stackoverflow.com/users/7412/dogbane
**
A recursive JavaScript (ES6) one-liner for any number of digits.
const gcd = (a, b, ...c) => b ? gcd(b, a % b, ...c) : c.length ? gcd(a, ...c) : Math.abs(a);
This is what comes off the top of my head in Javascript.
function calculateGCD(arrSize, arr) {
if(!arrSize)
return 0;
var n = Math.min(...arr);
for (let i = n; i > 0; i--) {
let j = 0;
while(j < arrSize) {
if(arr[j] % i === 0) {
j++;
}else {
break;
}
if(j === arrSize) {
return i;
}
}
}
}
console.log(generalizedGCD(4, [2, 6, 4, 8]));
// Output => 2
Here was the answer I was looking for.
The best way to find the gcd of n numbers is indeed using recursion.ie gcd(a,b,c)=gcd(gcd(a,b),c). But I was getting timeouts in certain programs when I did this.
The optimization that was needed here was that the recursion should be solved using fast matrix multiplication algorithm.

Searching a number in a rotated sorted Array

Given a Sorted Array which can be rotated find an Element in it in minimum Time Complexity.
eg : Array contents can be [8, 1, 2, 3, 4, 5]. Assume you search 8 in it.
The solution still works out to a binary search in the sense that you'll need to partition the array into two parts to be examined.
In a sorted array, you just look at each part and determine whether the element lives in the first part (let's call this A) or the second part (B). Since, by the definition of a sorted array, partitions A and B will be sorted, this requires no more than some simple comparisons of the partition bounds and your search key.
In a rotated sorted array, only one of A and B can be guaranteed to be sorted. If the element lies within a part which is sorted, then the solution is simple: just perform the search as if you were doing a normal binary search. If, however, you must search an unsorted part, then just recursively call your search function on the non-sorted part.
This ends up giving on a time complexity of O(lg n).
(Realistically, I would think that such a data structure would have a index accompanying it to indicate how many positions the array has been rotated.)
Edit: A search on Google takes me to this somewhat dated (but correct) topic on CodeGuru discussing the same problem. To add to my answer, I will copy some pseudocode that was given there so that it appears here with my solution (the thinking follows the same lines):
Search(set):
if size of set is 1 and set[0] == item
return info on set[0]
divide the set into parts A and B
if A is sorted and the item is in the A's range
return Search(A)
if B is sorted and the item is in the B's range
return Search(B)
if A is not sorted
return Search(A)
if B is not sorted
return Search(B)
return "not found"
O(log(N))
Reduced to the problem of finding the largest number position, which can be done by checking the first and last and middle number of the area, recursively reduce the area, divide and conquer, This is O(log(N)) no larger than the binary search O(log(N)).
EDIT:
For example, you have
6 7 8 1 2 3 4 5
^ ^ ^
By looking at the 3 numbers you know the location of the smallest/largest numbers (will be called mark later on) is in the area of 6 7 8 1 2, so 3 4 5 is out of consideration (usually done by moving your area start/end index(int) pointing to the number 6 and 2 ).
Next step,
6 7 8 1 2
^ ^ ^
Once again you will get enough information to tell which side (left or right) the mark is, then the area is reduced to half again (to 6 7 8).
This is the idea: I think you can refine a better version of this, actually, for an interview, an OK algorithm with a clean piece of codes are better than the best algorithm with OK codes: you 'd better hand-on some to heat-up.
Good luck!
I was asked this question in an interview recently.The question was describe an algorithm to search a "key" in a circular sorted array.I was also asked to write the code for the same.
This is what I came up with:
Use divide and conquer binary search.
For each subarray check if the array is sorted. If sorted use classic binary search
e.g
data[start]< data[end] implies that the data is sorted. user binary
else
divide the array further till we get sorted array.
public boolean search(int start,int end){
int mid =(start+end)/2;
if(start>end)
{
return false;
}
if(data[start]<data[end]){
return this.normalBinarySearch(start, end);
}
else{
//the other part is unsorted.
return (this.search(start,mid) ||
this.search(mid+1,end));
}
}
where normalBinarySearch is a simple binary search.
It a simple modification of normal binary search. In fact we it will work for both rotated and sorted arrays. In the case of sorted arrays it will end up doing more work than it really needs to however.
For a rotated array, when you split the array into two subarrays, it is possible one of those subarrays will not be in order. You can easily check if if each half is sorted by comparing the first and last value in the subarray.
Knowing whether each subarray is sorted or not, we can make a choice of what do do next.
1) left subarray is sorted, and the value is within the range of the left subarray (check both ends!)
Then search recursively search left subarray.
2) right subarray is sorted, and the value is within the range of the right subarray (check both ends!)
Then recursively search right subarray.
3) left is Not sorted
Then recursively search left subarray
4) Right is Not sorted
Then recursively search right subarray.
Note: the difference between this and a normal binary search is that we cannot simply choose the subarray to recurse on by simply comparing the last value left subarray (of first value of the right subarray) to make our decision. The value has to be strictly in the left or right subarray and that subarray has to sorted, otherwise we must recurse on the unsorted subarray.
Here is some Objective-C that implements this:
#implementation BinarySearcher
- (BOOL)isValue:(int)value inArray:(int[])array withArraySize:(int)size {
return [self subSearchArray:array forValue:value fromIndex:0 toIndex:size -1];
}
- (BOOL)subSearchArray:(int[])array forValue:(int)value fromIndex:(int)left toIndex:(int)right {
if (left <= right) {
int middle = (left + right) / 2;
BOOL leftArraySorted = array[left] <= array[middle];
BOOL rightArraySorted = array[middle + 1] <= array[right];
if (array[middle] == value) {
return YES;
} else if (leftArraySorted && value >= array[left] && value < array[middle]) {
return [self subSearchArray:array forValue:value fromIndex:left toIndex:middle];
} else if (rightArraySorted && value >= array[middle + 1] && value <= array[right]) {
return [self subSearchArray:array forValue:value fromIndex:middle + 1 toIndex:right];
} else if (!leftArraySorted) {
return [self subSearchArray:array forValue:value fromIndex:left toIndex:middle];
} else if (!rightArraySorted) {
return [self subSearchArray:array forValue:value fromIndex:middle + 1 toIndex:right];
}
}
return NO;
}
#end
At any index, one partition will be sorted and other unsorted. If key lies within sorted partition, search within sorted array, else in non sorted partition.
BS(lo, hi)
m = (lo + hi)/2
if(k = a[m])
return m
b = 0
if(a[hi] > a[m])
b = 1
if(b)
if(k > a[m] && k<a[hi])
BS(m+1, hi)
else
BS(lo, m-1)
Here is my approach at it:
public static int findMin(int[] a, int start, int end){
int mid = (start + end)/2;
if(start == mid){
return a[mid+1];
}else if(a[start] > a[mid]){
return findMin(a, start, mid);
}else if(a[mid+1] > a[start]){
return findMin(a, mid+1, end);
}else{
return a[mid+1];
}
}
Time complexity: O(log n)
You can wrap an array with a class that only exposes
E get(int index);
and would behave as regular sorted array.
For ex if you have 4 5 1 2 3 4, wrapper.get(0) will return 1.
Now you can just reuse binary search solution.
Wrapper can look like that:
class RotatedArrayWrapper<T> {
int startIndex;
private final List<T> rotatedArray;
public RotatedArrayWrapper(List<T> rotatedArray) {
this.rotatedArray = rotatedArray;
//find index of the smalest element in array
//keep in mind that there might be duplicates
startIndex = ...
}
public T get(int index) {
int size = rotatedArray.size();
if (index > size) throw Exception...
int actualIndex = (startIndex + index) % size;
return rotatedArray.get(actualIndex);
}
}
Python implementation. Could use to be more pythonic:
from bisect import bisect_left
def index(a, x):
"""Binary search to locate the leftmost value exactly equal to x.
see http://docs.python.org/2/library/bisect.html#searching-sorted-lists
>>> index([5, 14, 27, 40, 51, 70], 27)
2
>>> index([1, 2, 3, 4], 10)
Traceback (most recent call last):
...
ValueError
"""
i = bisect_left(a, x)
if i != len(a) and a[i] == x:
return i
raise ValueError
def _index_shifted(value, sequence, start, stop):
"""Recursive reset location and binary search"""
# if at reset (min) and it's not the value, it's not there
if start == stop and sequence[start] != value:
return -1
mid = (stop + start) // 2
# check mid, since we are already here
if sequence[mid] == value:
return mid
# right side is sorted
elif sequence[mid] < sequence[stop]:
# if value falls in range, search righ
if sequence[stop] >= value > sequence[mid]:
return index(sequence[mid:stop + 1], value) + mid
# partition left side
return _index_shifted(value, sequence, start, mid)
# left side is sorted
else:
# if value falls in range, search left
if sequence[mid] > value >= sequence[start]:
return index(sequence[start:mid], value) + start
# partition right side
return _index_shifted(value, sequence, mid + 1, stop)
def index_shifted(sequence, value):
"""Returns index of value in a shifted sorted sequence; -1 if not present.
>>> index_shifted([10, 13, 16, 19, 22, 25, 28, 31, 34, 37], 10)
0
>>> index_shifted([10, 13, 16, 19, 22, 25, 28, 31, 34, 37], 37)
9
>>> index_shifted([34, 37, 10, 13, 16, 19, 22, 25, 28, 31], 10)
2
>>> index_shifted([34, 37, 10, 13, 16, 19, 22, 25, 28, 31], 37)
1
>>> index_shifted([34, 37, 10, 13, 16, 19, 22, 25, 28, 31], 13)
3
>>> index_shifted([34, 37, 10, 13, 16, 19, 22, 25, 28, 31], 25)
7
>>> index_shifted([25, 28, 31, 34, 37, 10, 13, 16, 19, 22], 10)
5
>>> index_shifted([25, 28, 31, 34, 37, 10, 13, 16, 19, 22], -10)
-1
>>> index_shifted([25, 28, 31, 34, 37, 10, 13, 16, 19, 22], 100)
-1
"""
return _index_shifted(value, sequence, 0, len(sequence) - 1)
My solution:
efficiency: O(logn)
public static int SearchRotatedSortedArray(int l, int d, int[] array, int toFind) {
if (l >= d) {
return -1;
}
if (array[l] == toFind) {
return l;
}
if (array[d] == toFind) {
return d;
}
int mid = (l + d) / 2;
if (array[mid] == toFind) {
return mid;
}
if ((array[mid] > toFind && toFind > array[l]) || (array[mid] < toFind && array[d] < toFind)) {
return SearchRotatedSortedArray(l, mid - 1, array, toFind);
} else {
return SearchRotatedSortedArray(mid + 1, d, array, toFind);
}
}
//this solution divides the array in two equal subarrays using recurssion and apply binary search on individual sorted array and it goes on dividing unsorted array
public class SearchRotatedSortedArray
{
public static void main(String... args)
{
int[] array={5,6,1,2,3,4};
System.out.println(search(array,Integer.parseInt(args[0]),0,5));
}
public static boolean search(int[] array,int element,int start,int end)
{
if(start>=end)
{
if (array[end]==element) return true;else return false;
}
int mid=(start+end)/2;
if(array[start]<array[end])
{
return binarySearch(array,element,start,end);
}
return search(array,element,start,mid)||search(array,element,mid+1,end);
}
public static boolean binarySearch(int[] array,int element,int start,int end)
{
int mid;
while(start<=end)
{
mid=(start+end)/2;
if(array[mid]==element)
return true;
if(array[mid]<element)
{
start=mid+1;
}
else
{
end=mid-1;
}
}
return false;
}
}
int findIndexInRotatedSort( vector<int> input, int s, int e, int toFind )
{
if (s > e || s >= input.size() || e < 0)
{
return -1;
}
int m = (s + e)/2;
int sVal = input.at(s);
int eVal = input.at(e);
int mVal = input.at(m);
if (sVal == toFind)
return s;
if (eVal == toFind)
return e;
if (mVal == toFind)
return m;
bool isFirstOrdered = (sVal < mVal);
bool isSecondOrdered = (mVal < eVal);
if (toFind > mVal)
{
if (!isSecondOrdered || toFind < eVal)
{
return findIndexInRotatedSort( input, m+1, e, toFind );
}
else
{
return findIndexInRotatedSort( input, s, m-1, toFind );
}
}
else
{
if (!isFirstOrdered || toFind > sVal)
{
return findIndexInRotatedSort( input, s, m-1, toFind );
}
else
{
return findIndexInRotatedSort( input, m+1, e, toFind );
}
}
}
public class RoatatedSorted {
/**
* #param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] rotArray = {5,6,7,8,9,10,15,16,17,1,2,3,4,};
search(rotArray,0,rotArray.length-1,10);
}
private static void search(int[] a, int low, int high,int key) {
//int mid = low + (high-low)/2;
//if(a[mid]==a[key]){System.out.println("element found at" + key+1 +" position"); return;}
// find pos to split array
int pos = findSplitIndex(a,low,high);
System.out.println("split pos found at" + pos +" position");
if(key>=a[low]&& key <=a[pos])
bsearch(a,low,pos,key);
if(key>=a[pos+1]&& key <=a[high])
bsearch(a,pos+1,high,key);
}
private static void bsearch(int[] a, int low, int high,int key) {
// TODO Auto-generated method stub
if(low>high) return;
int mid = low + (high-low)/2;
if(a[mid]==key)
{System.out.println("element found at" + ++mid +" position"); return;}
if(a[mid] > key)
bsearch(a,low,mid-1,key);
if(a[mid]<key)
bsearch(a,mid+1,high,key);
}
private static int findSplitIndex(int[] a, int low, int high) {
// TODO Auto-generated method stub
int mid;
if(low>high)return -1;
while(true) {
mid = low + (high-low)/2;
if( a[mid]>a[mid+1])
break;
if(a[mid]>a[low])
low=mid;
if(a[high]>a[mid])
high=mid;
}
return mid;
}
}
First to find the Minimum element in the array then divide array in two part. After that search the given value using Binary search tree. Complexity : O(logn)
If you have to find the Minimum element in the rotated Array, use same approach,just skip Binary search. Complexity : O(logn)
//Search an element in a sorted and pivoted array
class SearchInPivotedSortedArray
{
//searchInOrtedPivotedArray : Return index of matched element with given value.
public static int searchInSortedPivotedArray(int[] A, int value)
{
int min = findMinElement(A,0,A.Length-1);
if (min == A[0])
return binarySearchTree(A, 0, A.Length-1, value);
if (value <= A[A.Length-1])
return binarySearchTree(A, min, A.Length-1, value);
else
return binarySearchTree(A, 0, min-1, value);
}
//return index of Pivot element
public static int findMinElement(int[] Array, int low, int high)
{
if (low >= high)
return low;
int mid = (low + high) / 2;
if (mid > low && Array[mid] < Array[mid - 1])
return mid;
if (mid < high && Array[mid] > Array[mid + 1])
return mid + 1;
if (Array[mid] < Array[high])
return findMinElement(Array, low, mid - 1);
return findMinElement(Array, mid + 1, high);
}
//Return match element index, if not found return -1
public static int binarySearchTree(int[] array, int low, int high,int value)
{
if (low > high)
return -1;
int mid = (low + high)/2;
if (array[mid] == value)
return mid;
if (array[mid] > value)
return binarySearchTree(array, low, mid - 1, value);
else
return binarySearchTree(array, mid + 1, high, value);
}
}
this is a O(logn) solution: tested. it works on both sorted and rotated sorted arrays:
public static int rbs(int[] a, int l, int r, int t) {
if (a[l] <= a[r]) {
return bs(a, l, r, t);
}
if (r < l) {
return -1;
} else {
int m = (l+r) / 2;
if (a[m] == t) {
return m;
} else if (a[m] > t) { // check left half
if (a[l] > a[m]) { // left is unsorted
return rbs(a, l, m-1, t);
} else { // left is sorted
if (a[l] < t) { // t is in range
return bs(a, l, m-1, t);
} else if (a[l] > t) { // t is out of range on left
if (a[r] >= t) {
return rbs (a, m+1, r, t);
} else
return -1;
} else
return l;
}
} else { // other side
if (a[r] < a[m]) { // right is unsorted
return rbs(a, m+1, r, t);
} else { // right is sorted
if (a[r] > t) { // t is in range
return bs(a, m+1, r, t);
} else if (a[r] < t) { // t is out of range on right side
if (a[l] <= t) {
return rbs (a, l, m-1, t);
} else
return -1;
} else
return r;
}
}
}
}
public static int bs(int[] a, int l, int r, int t) {
int m = (l+r) / 2;
if (r < l) {
return -1;
} else {
if (a[m] == t)
return m;
else if (a[m] < t)
return bs(a, m+1, r, t);
else
return bs (a, l, m-1, t);
}
}
Try out this solution,
public static int findElement(int[] a, int key, int left, int right) {
if (left > right) {
return -1;
}
int mid = (left + right) / 2;
if (key == a[mid]) {
return mid;
} else if (key < a[mid]) {
return (a[left] <= a[mid] && a[left] < key ? findElement(
a, key, left, mid - 1) : findElement(a, key,
mid + 1, right));
} else {
return (a[mid] <= a[right] && a[right] < key ? findElement(
a, key, left, mid - 1) : findElement(a, key,
mid + 1, right));
}
}
Here is a C++ implementation of #Andrew Song's answer
int search(int A[], int s, int e, int k) {
if (s <= e) {
int m = s + (e - s)/2;
if (A[m] == k)
return m;
if (A[m] < A[e] && k > A[m] && k <= A[e])
return search(A, m+1, e, k);
if (A[m] > A[s] && k < A[m] && k >= A[s])
return search(A, s, m-1, k);
if (A[m] < A[s])
return search(A, s, m-1, k);
if (A[m] > A[e])
return search(A, m+1, e, k);
}
return -1;
}
This is 100% working and tested solution in PYTHON
Program to find a number from a sorted but rotated array
def findNumber(a, x, start, end):
if start > end:
return -1
mid = (start + end) / 2
if a[mid] == x:
return mid
## Case : 1 if a[start] to a[mid] is sorted , then search first half of array
if a[start] < a[mid]:
if (x >= a[start] and x <= a[mid]):
return findNumber(a, x, start, mid - 1)
else:
return findNumber(a,x, mid + 1, end)
## Case: 2 if a[start] to a[mid] is not sorted , then a[mid] to a[end] mist be sorted
else:
if (x >= a[mid] and x <= a[end]):
return findNumber(a, x, mid + 1, end)
else:
return findNumber(a,x, start, mid -1)
a = [4,5,6,7,0,1,2]
print "Your array is : " , a
x = input("Enter any number to find in array : ")
result = findNumber(a, x, 0, len(a) - 1)
print "The element is present at %d position: ", result
In worst case you have to use linear search and examine whole array to find a target, because, unlike a set, an array may contain duplicates. And if an array contains duplicates you can't use binary search in the given problem.
If queries on particular array are infrequent you can use standard binary search if whole array is sorted (first element is strictly smaller than last element) and use linear search otherwise. For more information see How fast can you make linear search? discussion on StackOverflow and 10 Optimizations on Linear Search article by Thomas A. Limoncelli.
Hovewer, if queries are frequent you can sort input array in linear time (see Fastest algorithm for circle shift N sized array for M position discussion on StackOverflow) in preprocessing step and use standard binary search as usual.
#include<iostream>
using namespace std;
int BinarySearch(int *a,int key, int length)
{
int l=0,r=length-1,res=-1;
while(l<=r)
{
int mid = (l+r)/2;
if(a[mid] == key) {res = mid; break;}
//Check the part of the array that maintains sort sequence and update index
// accordingly.
if((a[mid] < a[r] && ( key > a[mid] && key <=a[r]))
|| a[mid] > a[r] && !( key>=a[l] && key <a[mid]))
{
l = mid+1;
}
else r = mid-1;
}
return res;
}
void main()
{
int arr[10] = {6,7,8,9,10,13,15,18,2,3};
int key = 8;
cout<<"Binary Search Output: "<<BinarySearch(arr,key,10);
}
Find element index in rotated sorted array
Example : [6,7,8,1,2,3,5]
int findElementIndex(int []a, int element, int start, int end)
{
int mid = (start + end)>>1;
if(start>end)
return -1;
if(a[mid] == element)
return mid;
if(a[mid] < a[start])
{
if(element <= a[end] && element > a[mid])
{
return findElementIndex(a,element,mid+1,end);
}
else{
return findElementIndex(a,element,start,mid-1);
}
}
else if(a[mid] > a[start]){
if(element >= a[start] && element < a[mid])
return findElementIndex(a,element,start,mid-1);
else
return findElementIndex(a,element,mid+1,end);
}
else if (a[mid] == a[start]){
if(a[mid] != a[end]) // repeated elements
return findElementIndex(a,element,mid+1,end);
else
int left = findElementIndex(a,element,start,mid-1);
int right = findElementIndex(a,element,mid+1,end);
return (left != -1) ? left : right;
}
}

Resources