question about counting sort - algorithm

hi i have write following code which prints elements in sorted order only one big problem is that it use two additional array
here is my code
public class occurance{
public static final int n=5;
public static void main(String[]args){
// n is maximum possible value what it should be in array suppose n=5 then array may be
int a[]=new int[]{3,4,4,2,1,3,5};// as u see all elements are less or equal to n
//create array a.length*n
int b[]=new int[a.length*n];
int c[]=new int[b.length];
for (int i=0;i<b.length;i++){
b[i]=0;
c[i]=0;
}
for (int i=0;i<a.length;i++){
if (b[a[i]]==1){
c[a[i]]=1;
}
else{
b[a[i]]=1;
}
}
for (int i=0;i<b.length;i++){
if (b[i]==1) {
System.out.println(i);
}
if (c[i]==1){
System.out.println(i);
}
}
}
}
//
1
2
3
3
4
4
5
1.i have two question what is complexity of this algorithm?i mean running time
2. how put this elements into other array with sorted order? thanks

The algorithm - as stated above - runs in O(n), where n is the size of array a.
However, I even doubt that it works correctly.
So, here's a pseudocode-implementation of counting sort. It takes an array a of integers and stores the sorted values in an integer array b. a and b must be of equal length.
void countingSort(int[] a, int[] b){
// first of all: count occurences
int[] occ = new int[a.length];
for (int i = 0; i<a.length; ++i){
occ[i]=0;
}
for (int i = 0; i<a.length; ++i){
occ[a[i]] = occ[a[i]] + 1;
}
// second: put the elements in order into b
int s = 0;
for (int i = 0; i<a.length; ++i){
// how often did element i occur?
for (int j = 0; j<occ[i]; ++j){
b[s] = i;
s = s + 1;
}
}
}
I hope I did nothing terribly wrong.

Related

Am I crazy for thinking this program is O(n) runtime? My TA says it's O(n^2)

Code below, it should be O(n). There are two loops, I know this. But that doesn't necessarily mean it's O(n^2). The function loops won't run more than n + 1 times (at least as far as I can tell!). That should be O(n). Am I wrong? Can someone help me out? Thanks!
EDIT: The program puts odd integers at the front and even integers at the back of an array!!!
public class Main {
public static void main(String[] args) {
int[] array = new int[]{5, 4, 3, 2, 1, 0};
organizeArray(array);
for (int j = 0; j < array.length; j++) {
System.out.println(array[j]);
}
}
public static void organizeArray(int[] array) {
int end = array.length - 1;
for (int i = 0; i < array.length; i++) {
int temp = 0;
while (true) {
if (i == end)
break;
if (array[i] % 2 == 0) {
temp = array[i];
array[i] = array[end];
array[end] = temp;
end = end - 1;
}
if (array[i] % 2 != 0)
break;
}
if (i == end)
break;
}
}
}
As the other question was a duplicate of this one, let me post my answer here.
The code is O(n) as you either increase i or reduce end. In any case, you decrease the rest of work (n) by one.
For your upcoming homework: You can test your thoughts about big-O easily just by trying out. Most of the time the number of tests doesn't need to be very big. It will not be a proof but it gives you a good hint if your thoughts are correct or not.
Here's is my code for your problem with 100 tests. It produces 100 pairs of numbers: The length of the array and the number of loops. You take this list and bring it to a graph.
public class Main {
public static void main(String[] args) {
Main main = new Main();
Random random = new Random();
for (int i = 0; i < 100; i++) {
int[] array = new int[random.nextInt(10000 - 10) + 10]; // between 10 and 9999 numbers long
for (int j = 0; j < array.length; j++) array[j] = random.nextInt();
main.organize(array);
}
}
private int[] organize(int[] array) {
long loops = 0;
int end = array.length-1;
// I've shorten your code here. This does the same with less breaks
for (int i = 0; i < end; i++) {
while(i < end && array[i] % 2 == 0) {
swap(array, i, end--);
loops++;
}
}
System.out.printf("%d\t%d\n", array.length, loops);
return array;
}
private void swap(int[] array, int a, int b) {
int t = array[a];
array[a] = array[b];
array[b] = t;
}
}
And the graph looks like a straight line. So your proof should result in O(n), right?
Interesting code. The inner for loop will break when the i'th element is odd. If its not odd then it will swap elements from the end until an odd one is found. Since end is decremented upon each swap and the program completes when i reaches end, it follows that i or end can get incremented/decremented, respectively at most O(n) times. Because of this, and because all other operations in the loops are O(1), the program indeed runs in time O(n) despite there being nested loops.

Split array of +ve and -ve nums

I am trying to solve this interview problem. I was able to get an O(N) solution with O(N) space complextity. I am trying to figure out if there is a solution with O(1) space?
Question:
Given an unsorted array of positive and negative numbers. Create an array of alternate positive and negative numbers without changing the relative order of positive and negative numbers respectively.
Input:
The first line of input contains an integer T denoting the number of test cases.
The first line of each test case is N,N is the size of array.
The second line of each test case contains N input a[].
Output:
Print an array of alternate positive and negative numbers.
Note: Solution should start with positive number.
Constraints:
1 ≤ T ≤ 30
1 ≤ N ≤ 100
-1000 ≤ a[] ≤ 1000
Example:
Input
1
9
9 4 -2 -1 5 0 -5 -3 2
Output
9 -2 4 -1 5 -5 0 -3 2
.
import java.util.*;
import java.lang.*;
import java.io.*;
class GFG {
public static void main (String[] args) {
//code
Scanner sn = new Scanner(System.in);
int T = sn.nextInt();
for(int i=0; i<T; i++){
int N = sn.nextInt();
ArrayList<Integer> arr = new ArrayList<Integer>();
ArrayList<Integer> pv_arr = new ArrayList<Integer>();
ArrayList<Integer> ne_arr = new ArrayList<Integer>();
for(int j=0; j<N; j++){
int num = sn.nextInt();
if(num<0){
ne_arr.add(num);
}else{
pv_arr.add(num);
}
}
int maxLen = Math.max(pv_arr.size(), ne_arr.size());
for(int k = 0; k < maxLen; k++){
if(k < pv_arr.size()){
System.out.print(pv_arr.get(k) + " ");
}
if(k < ne_arr.size()){
System.out.print(ne_arr.get(k) + " ");
}
}
System.out.println(" ");
}
}
}
My answer creates two arrays positive & negative and prints them alternatively. I tried using two pointers (one of positive values and one of negative values) I am not sure how to solve this with O(N) & O(1) space.
If you do not directly get an array as the input to your function but instead have to read the numbers from the standard input stream it means that you'll have to create the array yourself. Also the question states:
The first line...
The second line...
implying that the input is given to you line by line and not as parameters to a function.
This would mean that the best solution is O(n) in terms of space. You have already found a solution that works but you could still simplify it using a "pointer" approach like you had said yourself:
public static void main (String[] args) {
Scanner sn = new Scanner(System.in);
int T = sn.nextInt();
for(int i=0; i<T; i++){
int N = sn.nextInt();
int[] numbers = new int[N];
int neg_ind = 1;
int pos_ind = 0;
for(int j=0; j<N; j++){
int num = sn.nextInt();
if(num < 0){
numbers[neg_ind] = num;
neg_ind += 2;
}else{
numbers[pos_ind] = num;
pos_ind += 2;
}
}
System.out.println(Arrays.toString(numbers));
}
}

Algorithm Faster than QuickSort

I'm a beginner coder and I came up with an algorithm for sorting (DexSort) that typically works much faster than a standard Quicksort. This is assuming the number of ALL POSSIBLE values in a set/array is less than N^2, where N is the number of items I am trying to sort. I'm trying to find a way to optimize it so it doesn't necessarily have to depend on ALL POSSIBLE VALUES and just a subset of values that are relevant.
For example....say I have an array of random numbers where array.length = 10 million. My algorithm is only faster than Quicksort (on average) when the total number of all possible values is less than N^2 (i.e. 10^7 * 10^7 = 10 ^ 14). Now, say there are 10^14 actual values that can be found in an array. In this instant, my algorithm will run at roughly O(10^14). Can anyone think of a way to where I could reduce this?
Here is my code in Java:
package sort;
import java.util.*;
public class DexSort {
public static Comparable[] dexSort(Comparable[] c, int max){
//The variable int max is the maximum number of possible values
//E.g. If you are trying to sort 7-digit phone numbers, max = Math.pow(10,8) - 1, or 10^8 - 1
int size = c.length;
Comparable[] sorted = new Comparable[size];
int[] array = new int[max+1];
for (int i = 0; i < size; i++){
int val = (int) c[i];
int count = array[val];
count++;
array[val] = count;
}
int next = 0;
while (next < size){
for (int i = 0; i <= max; i++){
int count = array[i];
if (count > 0){
for (int j = 0; j < count; j++){
sorted[next] = i;
next++;
}
}
}
}
return sorted;
}
public static void main(String[] args){
Random r = new Random(7);
for (double n = 4; n < 8; n++){
double size = Math.pow(10, n);
System.out.println("---------------------------------------------");
System.out.println("Filling array size: 10^" + n);
System.out.println("---------------------------------------------\n");
Comparable[] array = fillArray((int)size, r); //Create array of random numbers of specified size
System.out.println("Array filled"); //Tests different array sizes by incrementing a power of 10
System.out.println("---------------------------------------------\n");
double max = size; //Arbitrarily set the maximum value possible as the array size
//Runtime will depend heavily on max if max>>>> size (See dexSort method)
//Overall, runtime will be O(max) when max >>>>> size
double t0 = System.nanoTime();
array = dexSort(array, (int) max);
double tF = System.nanoTime();
double nanoSecs = tF - t0;
double secs = nanoSecs/Math.pow(10, 9);
System.out.println("DEX sort complete");
System.out.println("It took " + String.format("%.3f", secs) + " seconds to sort an array of size 10^" + n);
//printArray(array); //Uncomment this line to print sorted array to console
System.out.println();
System.out.println("---------------------------------------------");
System.out.println("---------------------------------------------\n\n");
}
}
public static Comparable[] fillArray(int size, Random r){
Comparable[] c = new Comparable[size];
for (int i = 0; i < size; i++){
/*if ((i+1)%10000000 == 0){
System.out.println(((i+1)/1000000) + " million filled");
}*/
c[i] = r.nextInt(size)+1;
}
return c;
}
public static void printArray(Comparable[] c){
for (int i = 0; i < c.length; i++){
if (i%10 == 0){
System.out.println();
}
System.out.print(c[i] + "\t");
}
}
}

Reduce Time complexity of the following program

import java.util.Scanner;
class Special_Pairs{
private static Scanner scan;
public static void main(String [] args) {
byte t;
int n;
scan = new Scanner(System.in);
t=scan.nextByte();
int[] a=new int[100000];
while(t>0)
{
int i,j,count=0;
n=scan.nextInt();
for(i=0;i<n;i++)
{
a[i]=scan.nextInt();
}
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
{
if(((a[i]&a[j])==0)||((a[j]&a[i])==0))
{
count++;
}
}
}
t--;
System.out.println(count);
}
}
}
Help me reduce time complexity of this program
Question :
You have been given an integer array A on size N. You must report the number of ordered pairs (i,j) such that A[i] & A[j]=0.
Here & denotes the BITWISE AND (i,j) and (j,i) are considered different.
Input: First line contains T-Number of Test cases. First line of each test contains N. Next line contains N integers - the i'th integer A[i].
Output: Output the number of such pairs for each test case.
Constraints: T ≤ 10; N ≤ 100000; A[i] ≤ 1000000
Sample Input(Plaintext Link)
1
5
41 47 34 40 29
Sample Output(Plaintext Link)
2
Explanation: These are the required pairs (3 5) (5 3)
I would suggest three optimization for this. I have modified the code as well.
You need not to always start from 0 for each iteration of outer loop. The second loop can start from current+1 of the first loop. So will not be comparing elements which you have already compared.
You don't need to check for both pairs (i,j) and (j,i). If one is zero then other will always be zero.
You need not to initialize the array with fix size. You can always initialize it reading the value of n.
import java.util.Scanner;
public class Pairs {
public static void main(String [] args) {
Scanner scan = new Scanner(System.in);
int t = scan.nextInt();
while(t > 0) {
t--;
int count = 0;
int n = scan.nextInt();
int a[] = new int[n];
for(int i = 0; i<n; i++) {
a[i]=scan.nextInt();
}
for(int i = 0; i<n-1; i++) {
for(int j = i+1; j<n; j++) {
if((a[i] & a[j])==0)
{
count += 2;
}
}
}
System.out.println(count);
}
}
}
If you are competing on a programming contest (like ICPC or something like this), maybe you shouldn't use Scanner. It's too slow for reading from the keyboard. I've already competed at ICPC, but I used to use C++. Maybe you should try BufferedReader instead of Scanner.

interviewstreet Triplet challenge

There is an integer array d which does not contain more than two elements of the same value. How many distinct ascending triples (d[i] < d[j] < d[k], i < j < k) are present?
Input format:
The first line contains an integer N denoting the number of elements in the array. This is followed by a single line containing N integers separated by a single space with no leading/trailing spaces
Output format:
A single integer that denotes the number of distinct ascending triples present in the array
Constraints:
N <= 10^5
Every value in the array is present at most twice
Every value in the array is a 32-bit positive integer
Sample input:
6
1 1 2 2 3 4
Sample output:
4
Explanation:
The distinct triplets are
(1,2,3)
(1,2,4)
(1,3,4)
(2,3,4)
Another test case:
Input:
10
1 1 5 4 3 6 6 5 9 10
Output:
28
I tried to solve using DP. But out of 15 test cases only 7 test cases passed.
Please help solve this problem.
You should note that you only need to know the number of elements that are smaller/larger than a particular element to know how many triples it serves as the middle point for. Using this you can calculate the number of triples quite easily, the only remaining problem is to get rid of duplicates, but given that you are limited to at most 2 of the same element, this is trivial.
I solved using a Binary Index Tree http://community.topcoder.com/tc?module=Static&d1=tutorials&d2=binaryIndexedTrees.
I also did a small write up, http://www.kesannmcclean.com/?p=223.
package com.jai;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.HashMap;
public class Triplets {
int[] lSmaller, rLarger, treeArray, dscArray, lFlags, rFlags;
int size, count = 0;
Triplets(int aSize, int[] inputArray) {
size = aSize;
lSmaller = new int[size];
rLarger = new int[size];
dscArray = new int[size];
int[] tmpArray = Arrays.copyOf(inputArray, inputArray.length);
Arrays.sort(tmpArray);
HashMap<Integer, Integer> tmpMap = new HashMap<Integer, Integer>(size);
for (int i = 0; i < size; i++) {
if (!tmpMap.containsKey(tmpArray[i])) {
count++;
tmpMap.put(tmpArray[i], count);
}
}
count++;
treeArray = new int[count];
lFlags = new int[count];
rFlags = new int[count];
for (int i = 0; i < size; i++) {
dscArray[i] = tmpMap.get(inputArray[i]);
}
}
void update(int idx) {
while (idx < count) {
treeArray[idx]++;
idx += (idx & -idx);
}
}
int read(int index) {
int sum = 0;
while (index > 0) {
sum += treeArray[index];
index -= (index & -index);
}
return sum;
}
void countLeftSmaller() {
Arrays.fill(treeArray, 0);
Arrays.fill(lSmaller, 0);
Arrays.fill(lFlags, 0);
for (int i = 0; i < size; i++) {
int val = dscArray[i];
lSmaller[i] = read(val - 1);
if (lFlags[val] == 0) {
update(val);
lFlags[val] = i + 1;
} else {
lSmaller[i] -= lSmaller[lFlags[val] - 1];
}
}
}
void countRightLarger() {
Arrays.fill(treeArray, 0);
Arrays.fill(rLarger, 0);
Arrays.fill(rFlags, 0);
for (int i = size - 1; i >= 0; i--) {
int val = dscArray[i];
rLarger[i] = read(count - 1) - read(val);
if (rFlags[val] == 0) {
update(val);
rFlags[val] = i + 1;
}
}
}
long countTriplets() {
long sum = 0;
for (int i = 0; i < size; i++) {
sum += lSmaller[i] * rLarger[i];
}
return sum;
}
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int N = Integer.parseInt(br.readLine());
int[] a = new int[N];
String[] strs = br.readLine().split(" ");
for (int i = 0; i < N; i++)
a[i] = Integer.parseInt(strs[i]);
Triplets sol = new Triplets(N, a);
sol.countLeftSmaller();
sol.countRightLarger();
System.out.println(sol.countTriplets());
}
}
For tentative algorithm that I came up with, it should be:
(K-1)!^2
where K is number of unique elements.
EDIT
After more thinking about this:
SUM[i=1,K-2] SUM[j=i+1,K-1] SUM[m=j+1,K] 1
=> SUM[i=1,K-2] (SUM[j=i+1,K-1] (K-j))
if the input is not sorted (the question is not clear about this): sort it
remove the duplicated items (this step could be conbined with the first step)
now pick 3 items. Since the items are already sorted, the three chosen items are ordered as well
IIRC there are (n!) / ((n-3)! * 3!) ways to pick the three items; with n := the number of unique items
#hadron: exactly, I couldn get my head around on why it should be 28 and not 35 for a set of 7 distinct numbers *
[Since the ques is about ascending triplets, repeated numbers can be discarded].
btw, here's a very bad Java solution(N^3):
I have also printed out the possible triplets:
I'm also thinking about some function that dictates the no: of triplets possible for input 'N'
4 4
5 10
6 20
7 35
8 56
9 84
package org.HackerRank.AlgoChallenges;
import java.util.Iterator;
import java.util.Scanner;
import java.util.TreeSet;
public class Triplets {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int result = 0;
int n = scanner.nextInt();
Object[] array = new Object[n];
TreeSet<Integer> treeSet = new TreeSet<Integer>();
/*
* for (int i = 0; i < n; i++) { array[i] = scanner.nextInt(); }
*/
while (n>0) {
treeSet.add(scanner.nextInt());
n--;
}
scanner.close();
Iterator<Integer> iterator = treeSet.iterator();
int i =0;
while (iterator.hasNext()) {
//System.out.println("TreeSet["+i+"] : "+iterator.next());
array[i] = iterator.next();
//System.out.println("Array["+i+"] : "+array[i]);
i++;
}
for (int j = 0; j < (array.length-2); j++) {
for (int j2 = (j+1); j2 < array.length-1; j2++) {
for (int k = (j2+1); k < array.length; k++) {
if(array[j]!=null && array[j2]!=null && array[k]!=null){
System.out.println("{ "+array[j]+", "+array[j2]+", "+array[k]+" }");
result++;
}
}
}
}
System.out.println(result);
}
One of solution in python:
from itertools import combinations as comb
def triplet(lis):
done = dict()
result = set()
for ind, num in enumerate(lis):
if num not in done:
index = ind+1
for elm in comb(lis[index:], 2):
s,t = elm[0], elm[1]
if (num < s < t):
done.setdefault(num, None)
fin = (num,s,t)
if fin not in result:
result.add(fin)
return len(result)
test = int(raw_input())
lis = [int(_) for _ in raw_input().split()]
print triplet(lis)
Do you care about complexity?
Is the input array sorted?
if you don't mind about complexity you can solve it in complexity of N^3.
The solution with complexity N^3:
If it not sorted, then sorted the array.
Use 3 for loops one inside the other and go threw the array 3 times for each number.
Use hash map to count all the triples. The key will be the triple it self and the value will be the number of occurences.
It should be something like this:
for (i1=0; i1<N; i1++) {
for (i2=i1; i2<N; i2++) {
for (i3=i2; i3<N; i3++) {
if (N[i1] < N[i2] < N[i3]) {
/* if the triple exists in the hash then
add 1 to its value
else
put new triple to the hash with
value 1
*/
}
}
}
}
Result = number of triples in the hash;
I didn't try it but I think it should work.

Resources