bit twiddling in java - power set, ordered by size - java

Following up my previous bit-twiddling question, now I'm looking to trim down the method that uses that one (though, an unbuffered version, since the life of the array is only this object). This is the iterator method for a power set of some long base; the actual contents of the set isn't stored - it would be a memory hog and individual members are only interesting when one wants to iterate over the set - so the members are generated by the iterator.
However, those members need to be returned in order by size first (instead of lexicographical order) - i.e., "sorted" by bit count.
Below is my (working) first cut; any suggestions from optimization addicts? This one I'm pretty sure has more obvious cuts.
public Iterator<Long> iterator() { return new Iterator<Long>(){
private boolean hasNext = true;
#Override public boolean hasNext() { return hasNext; }
private final long[] split = BitTwiddling.decompose(base);
int size = 0;
private long next = 0;
private long lastOfSize = 0;
private long firstOfSize = 0;
int[] positions = new int[split.length];
#Override
public Long next() {
long result = next;
if (next == lastOfSize) {
if (size == split.length) {
hasNext = false;
return result;
}
next = (firstOfSize |= split[size]);
lastOfSize |= split[split.length - ++size];
for(int i=0; i<size; i++) positions[i] = i;
} else {
if (positions[size-1] == split.length-1) {
int index = size-1;
int ref = split.length - 1;
while (positions[index] == ref) { index--; next ^= split[ref--]; }
next ^= split[positions[index]++];
next |= split[positions[index++]];
do {
next |= split[positions[index] = positions[index-1]+1];
} while (++index < size);
} else {
next ^= split[positions[size-1]++];
next |= split[positions[size-1]];
}
}
return result;
}

If I understand the question correctly, you want to Compute the lexicographically next bit permutation

Related

First Unique Character In a String-Leetcode

I have tried out 387.First Unique Character In A string
Given a string s, find the first non-repeating character in it and
return its index. If it does not exist, return -1.
EXAMPLE : 1
Input: s = "leetcode"
Output: 0
EXAMPLE :2
Input: s = "loveleetcode"
Output: 2
I have been trying this problem. I thought we will pick one by one all the characters and check if a repeating character exists break from the loop. And if not then return that index.I have thought over a solution which I believe is not the most efficient way but I want to know the how can I solve this problem with the approach given below:
public int firstUniqChar(String s) {
for(int i=0;i<s.length();i++){
for(int j=i+1;j<s.length();j++){
if(s.charAt(i)==s.charAt(j)){
break;
}
}
}
return -1;
}
I'm confused how to return the index.I'm unable to find the logic after:
for(int j=i+1;j<s.length();j++){
if(s.charAt(i)==s.charAt(j)){
break;
}
}
If anyone can help me find out the logic here.
Try this.
public static int firstUniqChar(String s) {
L: for (int i = 0, length = s.length(); i < length; i++) {
for (int j = 0; j < length; j++)
if (i != j && s.charAt(i) == s.charAt(j))
continue L;
return i;
}
return -1;
}
public static void main(String[] args) {
System.out.println(firstUniqChar("leetcode"));
System.out.println(firstUniqChar("loveleetcode"));
System.out.println(firstUniqChar("aabb"));
}
output:
0
2
-1
you can use a flag variable.
public int firstUniqChar(String s) {
int flag=0;
for(int i=0;i<s.length();i++){
flag=0;
for(int j=0;j<s.length();j++){
if(s.charAt(i)==s.charAt(j) && i!=j){
flag=1;
break;
}
}
if(flag==0){
return i;
}
}
return -1;
}
There are 26 possible lowercase English letters, so you could use two 26 element arrays.
One array, letterCount, keeps counts of each letter. Start at 0 and add 1 every time the corresponding letter appears in the text string. The second array, position, holds the position of the first occurrence of that letter, or -1 if the letter never appears. You will need to initialise that array to -1 for all elements.
Process the string in order, recording initial positions, once only for each letter, and incrementing the count for each letter in the string.
After the string has been processed, look through the letterCount array. If there are no letters with a 1 count then return -1. If exactly one letter has a 1 count, then return the position of that letter from the position array. If more than one letter has a 1 count, then pick the one with the lowest value for its position.
Using two loops is a highly inefficient way of solving this problem. The string can be up to 100,000 characters long and you are processing it multiple times. Far better to process it only once, keeping track of what you have found so far.
Fix you code
You need to add a variable that tells you if you have breaked the loop or not
static int firstUniqChar(String s) {
boolean duplicate;
for (int i = 0; i < s.length(); i++) {
duplicate = false;
for (int j = i + 1; j < s.length(); j++) {
if (s.charAt(i) == s.charAt(j)) {
duplicate = true;
break;
}
}
if (!duplicate) {
return i;
}
}
return -1;
}
Improve
There is a smarter way, that is finding the last index occurence of the current char, if it's equal to the current index : that char is unique and you return its index
static int firstUniqChar(String s) {
for (int i = 0; i < s.length(); i++) {
if (s.lastIndexOf(s.charAt(i)) == i) {
return i;
}
}
return -1;
}
If you do not bother about time complexity using IdenxOF operations, then one can try this solution.
indexOf() – also runs in linear time. It iterates through the internal array and checking each element one by one. So the time
complexity for this operation always requires O(n) time.
int firstUniqCharOneLoop(String str) {
for (int i = 0; i < str.length(); i++) {
if (str.indexOf(str.charAt(i))== str.lastIndexOf(str.charAt(i)) ) {
return i;
}
}
return -1;
}
The lowest complexity I managed to achieve:
public class UniqueSymbolFinder {
static int findFirstUniqueChar(String s) {
Set<Character> set = new HashSet<>(s.length());
List<CharWithIndex> candidates = new LinkedList<>();
for (int i = 0; i < s.length(); i++) {
char ch = s.charAt(i);
CharWithIndex charWithIndex = new CharWithIndex(ch, i);
if (set.add(ch)) {
candidates.add(charWithIndex);
} else {
candidates.remove(charWithIndex);
}
}
return candidates.size() == 0 ? -1 : candidates.get(0).index;
}
/**
* Class for storing the index.
* Used to avoid of using an indexOf or other iterations.
*/
private static class CharWithIndex {
int index;
char ch;
private CharWithIndex(char ch, int index) {
this.ch = ch;
this.index = index;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
CharWithIndex that = (CharWithIndex) o;
return ch == that.ch;
}
#Override
public int hashCode() {
return Objects.hash(ch);
}
}
}
I believe the memory usage can still be optimized.
100% Correct JAVA Solution
Since the question is about returning the index of the first non-repeating character in a string, we need some data structure to save the index of each character in the string for us.
I choose here the HashMap of Java. Basically, what you can do with it, you can save a pair of values (or pair of other data structures).
So, in my solution, I am saving a Character Integer pair. The first is considered as a key (here it is each character in the string), and the second is its index value.
The problem here is that we only want to keep the minimum index of non-repeating characters and that's why if you take a look below, you will find the maxIndexForRepeatedValues is set to be 10 power 5 as the input constraint says 1 <= s.length <= 10 power 5.
However, I am using that value to neglect repeated characters that would be found in the HashMap and at the end, we retrieve the minimum index which is the index of course for the first character from the map, or if there were only repeated characters, we return -1.
To make the code shorter, I used ternary-operator but you can write it with if-else if you want!
class Solution {
public int firstUniqChar(String s) {
int maxIndexForRepeatedValues = 100000;
Map<Character, Integer> map = new HashMap<>();
for (int i = 0 ; i < s.length() ; i++) {
char key = s.charAt(i);
int resIndex = map.containsKey(key) ? maxIndexForRepeatedValues : i;
map.put(key, resIndex);
}
int minIndex = Collections.min(map.values());
return minIndex == maxIndexForRepeatedValues ? -1 : minIndex;
}
}

How to use binary search of a sorted list and then count the comparisons

I am trying to use my sorted list and implement it with binary search. Then i want to count the number of comparisons it takes to find the key. my code is:
public class BinarySearch {
private static int comparisions = 0;
public static void main(String[] args) {
int [] list = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20};
int i = BinarySearch.BinSearch(list, 20);
System.out.println(comparisions);
}
public static int BinSearch(int[] list, int key) {
int low = 0;
int high = list.length - 1;
int mid = (high + low) / 2;
if (key < list[mid]) {
high = mid - 1;
comparisions++;
} else if (key == list[mid]) {
return mid;
comparisions++;
} else {
low = mid + 1;
comparisions++;
}
return -1;
}
}
So far it only gives me 1 for the comparison no matter what number is the key.
Your code is missing the looping part of the search, that looping can either be done using recursion or using a while loop. In both cases you have to ask yourself wether or not you just want to know the count or actually return the count of comparisons. Since your method right now returns the index, it cannot easily return the count of comparisons at the same time. For that to work you either need to return an array of two ints or a custom class IndexAndComparisonCount { ... }.
If you use a recursive approach you need to increment whenever you do a comparison and when you do a recursive call you need to get the return value of that recursive call and increment the comparisonCount the call returned by 1:
if (... < ...) {
IndexAndComparisonCount ret = BinSearch(...);
ret.comparisonCount += 1;
return ret;
} else if (... > ...) {
IndexAndComparisonCount ret = BinSearch(...);
ret.comparisonCount += 2; // since you did compare twice already
return ret;
} else {
return new IndexAndComparisonCount(mid, 2); // you compared twice as well
}

Bubble Sort with compare method not running

This is a follow-up to my previous question that I asked yesterday. I wrote a Bubble Sort method that analyzes an array of strings and returns the NUMBER of comparisons that the method has made when ordering the array into alphabetical order (the assignment is to write several types of sorting methods and graph the number of comparisons each one makes, to see which is most efficient).
This is my code:
public static void main(String[] args)
{
String[] test_array = {"bill", "phil", "adam"};
/*
System.out.println(compare("orange", "boogie"));
*/
System.out.println(bubbleSort(test_array));
}
public static int compare(String a, String b)
{
int len = Math.min (a.length(),b.length());
// looping through every character. If cha is less than chb, the method returns -1, and so on.
for (int i = 0; i<len; i++) {
char cha = a.charAt(i);
char chb = b.charAt(i);
if (cha < chb) {
return -1;
} else if (cha > chb) {
return 1;
}
}
// Now we account for the length of the word, since it could be the same word.
if (a.length() < b.length())
return -1;
else if (a.length() > b.length())
return 1;
// Seems to be the same String, so return 0.
else
return 0;
}
public static int bubbleSort(String[] test_array) {
boolean swapped = true;
// Variable to track number of comparisons.
int compNumber = 0;
while (swapped == true) {
swapped = false;
for (int i = 1; i < test_array.length; i++) {
// Tracking the number of comparisons
compNumber++;
if (compare(test_array[i-1], test_array[i]) > 0) {
//Switching the variables by use of a temp variable
String temp = test_array[i-1];
test_array[i-1] = test_array[i];
test_array[i] = temp;
swapped = true;
}
else {
swapped = true;
}
}
}
return compNumber;
}
So the compare method compares two strings (given by the array) and determines if they are in alphabetical order (returns -1) or not (returns 1), or is the same word (returns 0). Then, the bubble sort method calls upon the compare method to go through the array, and it then makes the switches, while my compNumber variable counts the number of times the loop (therefore the number of comparisons) runs.
It compiles fine, but it unfortunately doesn't stop running and doesn't return anything. I've waited 5 minutes so I've determined that something is wrong, probably with my loops. I can't seem to find an issue, having manipulated the parameters of the loops several times. Could anyone help me out? Thanks in advance.
"swapped" will always be true, hence the while will never end looping.
I think you meant to put swapped = false in the else statement
you need to set one of these two swapped = false... or else you will never exit the while loop because swapped = true always ... probably changing the second one makes sense !
if (compare(test_array[i-1], test_array[i]) > 0) {
//Switching the variables by use of a temp variable
String temp = test_array[i-1];
test_array[i-1] = test_array[i];
test_array[i] = temp;
swapped = true;
}
else {
swapped = true;
}

Complexity and Efficiency in Algorithm for: a[j]-a[i] i>=j

I'm looking to make this much quicker. I've contemplated using a tree, but I'm not sure if that would actually help much.
I feel like the problem is for most cases you don't need to calculate all the possible maximums only a hand full, but I'm not sure where to draw the line
Thanks so much for the input,
Jasper
public class SpecialMax {
//initialized to the lowest possible value of j;
public static int jdex = 0;
//initialized to the highest possible value of i;
public static int idex;
//will hold possible maximums
public static Stack<Integer> possibleMaxs = new Stack<Integer> ();
public static int calculate (int[] a){
if (isPositive(a)){
int size = a.length;
int counterJ;
counterJ = size-1;
//find and return an ordered version of a
int [] ordered = orderBySize (a);
while (counterJ>0){
/* The first time this function is called, the Jvalue will be
* the largest it can be, similarly, the Ivalue that is found
* is the smallest
*/
int jVal = ordered[counterJ];
int iVal = test (a, jVal);
possibleMaxs.push(jVal-iVal);
counterJ--;
}
int answer = possibleMaxs.pop();
while (!possibleMaxs.empty()){
if (answer<possibleMaxs.peek()){
answer = possibleMaxs.pop();
} else {
possibleMaxs.pop();
}
}
System.out.println("The maximum of a[j]-a[i] with j>=i is: ");
return answer;
} else {
System.out.println ("Invalid input, array must be positive");
return 0; //error
}
}
//Check to make sure the array contains positive numbers
public static boolean isPositive(int[] a){
boolean positive = true;
int size = a.length;
for (int i=0; i<size; i++){
if (a[i]<0){
positive = false;
break;
}
}
return positive;
}
public static int[] orderBySize (int[] a){
//orders the array into ascending order
int [] answer = a.clone();
Arrays.sort(answer);
return answer;
}
/*Test returns an Ival to match the input Jval it accounts for
* the fact that jdex<idex.
*/
public static int test (int[] a, int jVal){
int size = a.length;
//initialized to highest possible value
int tempMin = jVal;
//keeps a running tally
Stack<Integer> mIndices = new Stack<Integer> ();
//finds the index of the jVal being tested
for (int i=0; i<size; i++) {
if (jVal==a[i]){
//finds the highest index for instance
if (jdex<i){
jdex = i;
}
}
}
//look for the optimal minimal below jdex;
for (int i=0; i<jdex; i++){
if (a[i]<tempMin){
tempMin = a[i];
mIndices.push(i);
}
}
//returns the index of the last min
if (!mIndices.empty()){
idex = mIndices.pop();
}
return tempMin;
}
}
It can be done in linear time and linear memory. The idea is: find the minimum over each suffix of the array and maximum over each prefix, then find the point where the difference between the two is the highest. You'll also have to store the index on which the maximum/minimum for each prefix is reached if you need the indices, rather than just the difference value.
Pre-sorting a[] makes the procedure complicated and impairs performance. It is not necessary, so we leave a[] unsorted.
Then (EDITED, because I had read j>=i in the body of your code, rather than i>=j in the problem description/title, which I now assume is what is required (I didn't go over your coding details); The two varieties can easily be derived from each other anyway.)
// initialize result(indices)
int iFound = 0;
int jFound = 0;
// initialize a candidate that MAY replace jFound
int jAlternative = -1; // -1 signals: no candidate currently available
// process the (remaining) elements of the array - skip #0: we've already handled that one at the initialization
for (int i=1; i<size; i++)
{
// if we have an alternative, see if that combines with the current element to a higher "max".
if ((jAlternative != -1) && (a[jAlternative]-a[i] > a[jFound]-a[iFound]))
{
jFound = jAlternative;
iFound = i;
jAlternative = -1;
}
else if (a[i] < a[iFound]) // then we can set a[iFound] lower, thereby increasing "max"
{
iFound = i;
}
else if (a[i] > a[jFound])
{ // we cannot directly replace jFound, because of the condition iFound>=jFound,
// but when we later may find a lower a[i], then it can jump in:
// set it as a waiting candidate (replacing an existing one if the new one is more promising).
if ((jAlternative = -1) || (a[i] > a[jAlternative]))
{
jAlternative = i;
}
}
}
double result = a[jFound] - a[iFound];

How can i make this Java queue display() method work with all array sizes instead of just [5]?

// Queue.java
// demonstrates queue
// to run this program: C>java QueueApp
class Queue
{
private int maxSize;
private long[] queArray;
private int front;
private int rear;
private int nItems;
public Queue(int s) // constructor
{
maxSize = s;
queArray = new long[maxSize];
front = 0;
rear = -1;
nItems = 0;
}
public void insert(long j)
{
if(rear == maxSize-1)
rear = -1;
queArray[++rear] = j;
nItems++;
}
public long remove()
{
long temp = queArray[front++];
if(front == maxSize)
front = 0;
nItems--;
return temp;
}
public long peekFront()
{
return queArray[front];
}
public boolean isEmpty() // true if queue is empty
{
return (nItems==0);
}
public boolean isFull() // true if queue is full
{
return (nItems==maxSize);
}
public int size() // number of items in queue
{
return nItems;
}
public void display()
{ int startFront = front;
for (int j = front ;j <nItems; j++ )
{
System.out.println(queArray[j]);
if (j == nItems-1 )
{ j=0;
System.out.println(queArray[j]);
}
if (j==startFront-1)
return;
}
}
}
class QueueApp
{
public static void main(String[] args)
{
Queue theQueue = new Queue(5); // queue holds 5 items
theQueue.insert(10); // insert 4 items
theQueue.insert(20);
theQueue.insert(30);
theQueue.insert(40);
theQueue.remove(); // remove 3 items
theQueue.remove(); // (10, 20, 30)
theQueue.remove();
theQueue.insert(50); // insert 4 more items
theQueue.insert(60); // (wraps around)
theQueue.insert(70);
theQueue.insert(80);
theQueue.display();
while( !theQueue.isEmpty() ) // remove and display
{ // all items
long n = theQueue.remove(); // (40, 50, 60, 70, 80)
System.out.print(n);
System.out.print(" ");
}
System.out.println("");
} // end main()
} // end class QueueApp
Okay, this is the basic, out of the book, queue code. I am attempting to create a display method that will show the queue in order, from front to back. (This is an assignment, i know this is not practical....) If i run the program as is, it will display the queue in order from front to rear(at least that is what i believe i did). The problem i am having is if i change the nItems, it ceases to work. For example if you add the line of code, theQueue.remove(); right above the call to the display, the method ceases to work, i know it is because the front is now = to 4, instead of 3,and it will not enter the for method which needs the front to be < nItems, 4<4 is not true so the for loop does not initiate.
Simply use something like:
public void display() {
for (int i = 0; i < nItems; i++) {
System.out.println(queArray[(front + i) % maxSize]);
}
}
In my opinion you're using too many variables which you don't need. You only need the Queue size and its item count.
public Queue(int s) {
size = s;
queArray = new long[s];
nItems = 0;
}
public void insert(long j) {
if(nItems < size) {
queArray[nItems] = j;
nItems++;
}
}
public long remove() {
if(nItems > 0) {
long temp = queArray[nItems];
nItems--;
return temp;
}
}
public void display() {
for(int j = 0; j < nItems; j++) {
System.out.println(queArray[j]);
}
}
So what's happening right now is that j is the position of the element in your array, which is different from the number of elements that you've printed so far.
You need to either use a different index to count how many elements you printed or check whether you're at the end by comparing j to rear.
When the queue is full (rear == maxSize - 1) and you do a insert, it will replace the first
item, so i think the line nItems++ should not be incremented when the queue is already full.
Edit: Avoid modulus operations when you don't need them, they consume a lot of cpu.
The backing store for your queue is :
private long[] queArray;
Why don't you instead use :
private List<Long> queArray
and let List worry about the resizing effort after add/remove operations. Your current queue implementation needs to know exactly how many elements are going into the queue on construction. That's pretty inconvenient for clients using this API.
You can instantiate the queArray as :
queArray = new ArrayList<Long>();
in your constructor. Once you really understand that code, you can then move onto worrying about the re-sizing logic yourself.

Categories

Resources