Currently working on a java program that does a bunch of functions, and one of those functions is to delete a range of alphabetized words. I am using animals as an example.
Here is the display list prior to executing the deleteRange function:
cat
chinchilla
horse
mouse
rat
I ask the program to delete chinchilla to mouse, but it doesn't include horse.
public boolean deleteRange(String start, String stop){
boolean result = false;
int begin = Find(start);
int end = Find(stop);
while(begin<end){
Delete(storage[begin]);
begin++;
result = true;
}
return result;
}
My delete function:
public boolean Delete(String value){
boolean result = false;
int location;
location = Find(value);
if (location >= 0) {
moveItemsUp(location);
numUsed--;
result = true;
}
return result;
}
My find function:
public int Find(String value) {
int result = -1;
int index = 0;
boolean found = false;
while ((index < numUsed) && (!found)) {
found = (value.equals(storage[index]));
if (!found)
index++;
}
if (found)
result = index;
return result;
}
My moveitemsup function:
private void moveItemsUp(int start){
int index;
for (index = start; index < numUsed-1; index++){
storage[index] = storage[index+1];
}
}
So, you are deleting array indices 1 -3 --
After you delete array index 1, your former index 3 now becomes 2 AND you are incrementing "begin" .. So now you delete index 2.. which in this case is mouse .. so horse gets skipped .
Instead, you want to keep the number of elements to delete ( end - begin + 1 )
int count = end - begin + 1;
while ( count > 0 ) {
Delete(storage[begin]);
}
something along those lines.
Why don't you try something like this if your list is in an ArrayList (no Java stuff on this box so this hasn't been tested) .
public boolean deleteRange( String start, String stop ) {
for(Iterator<String> iter = storage.iterator();iter.hasNext();) {
String element = iter.next();
if(element.compareTo(start) >= 0 && element.compareTo(stop) <= 0 ) {
iter.remove();
}
}
}
The problems I can see are:
problem 1
you increase begin index and "shrink (not really shrink)" the array at same time, after each deletion.
for example
[a,b,c,d,e,f], say you want to delete b-e index 1-4
first you deleted b (index 1) then you moveItemsUp after deletion. so array is:
[a,c,d,e,f,f], then you begin++ begin is 2, which pointing d, jumped over c
problem 2
if you fixed problem 1, there is another thing you should consider about, after deletion, the array would be [a,f,f,f,f,f] if it is what you wanted.
btw, why not consider to use LinkedList ? it should be much faster for deletion.
int begin = Find(start);
int end = Find(stop);
int count = end - begin;
for (int i=0; i <= count; i++){
Delete(storage[begin]);
result = true;
changed some code to this, made it work =)
Related
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;
}
}
I am trying to solve a question in which I am given a String array of words and I have to check whether they have all same length or not. For instance if am given the array {"apple","purple","lemon"} then my method should return true, and when I am given the array {"red","blue"}, it should return false.
This is what I did so far but it is not working. I appreciate any help.
public static boolean allEqualLength(String[] myArray){
int i;
for(i=0;i<myArray.length;i++){
if(myArray[i]!=myArray[i+1])
return false;
}
return true,
}
All items having the same length is equivalent to saying all items must have the same length as the first item:
public static boolean allEqualLength(String[] myArray) {
// zero items => "all" items have same length:
if (myArray.length == 0) return true;
final int expectedLength = myArray[0].length();
for(int i = 0; i < myArray.length; ++i) {
if(myArray[i].length() != expectedLength)
return false;
}
return true,
}
But your original solution was not that far off. You just need to make sure not to exceed the array's bounds and to compare the string lengths, not the strings themselves:
public static boolean allEqualLength(String[] myArray) {
for(int i=0; i < myArray.length - 1; i++) { // -1 to not exceed bounds
if(myArray[i].length() != myArray[i+1].length()) // compare length, not memory addresses
return false;
}
return true,
}
I world do something like that:
public static boolean allEqualLength(String[] myArray) {
int strLength = myArray[0].length();
for (String str :
myArray) {
if (str.length() != strLength)
return false;
}
return true;
}
Like that you can avoid any indexing problems in your loop.
You are trying to compare the strings themselves. You should compare the length only.
myArray[i].length() != myArray[i + 1].length()
By the way, this will throw an ArrayIndexOutOfBoundsException, because you are trying to access index myArray[myArray.length]. Change the for loop to
for (int i = 0; i < myArray.length - 1; i++) {
if (myArray[i].length() != myArray[i + 1].length()) {
return false;
}
}
Also make sure you return true if the array length is 0 or 1, because the loop can't handle those.
For example you have array with length 4 , you have the positions 0,1,2,3 so in your code you run with : myArray[i]!=myArray[i+1] so on the last run you check the positions :
3 and 4 and you will get ArrayIndexOutOfBoundsException , you need to change to : length-1 on the loop condition like this :
public static boolean allEqualLength(String[] myArray){
int i;
for(i=0;i<myArray.length -1;i++){
if(myArray[i].length() != myArray[i+1].length())
return false;
}
return true,
}
If you run on myArray.length ,the positions that check :
0--1
1--2
2--3
3--4 // ERROR !!! ArrayIndexOutOfBoundsException !!
If you run on myArray.length-1 ,the positions that check :
0--1
1--2
2--3 -OK !!!
So on this way if you run the array with : myArray.length-1 , you will not get ArrayIndexOutOfBoundsException .
First things first you are not checking element lengths other issue is your for loop would try to access array index out of bounds since you have i+1, last element is already being checked that way, considering that you just need for until myArray.length - 1.
Using your code it would look something like this:
public static boolean allEqualLength(String[] myArray) {
for (int i = 0; i < myArray.length - 1; i++) {
if (myArray[i].length() != myArray[i + 1].length())
return false;
}
return true;
}
If performance is not an issue and you will not use it in 1 million strings or something, in addition to all these answers, here is an one liner:
boolean allStringsEqualLength = Stream.of(array)
.map(String::length).distinct().count() == 1;
The idea is to map each string to its length. So if distinct() stream contains only one value, that means all strings had the same length.
I have the array {1,2,3,4,4,4,5}
I want my function return index of 4.
for example : 4 found at location 4,5,6
public void binarySearch(int value){
sort(); // sorting the array
int index=-1;
int lower=0;
int upper=count-1;
while(lower<=upper){
int middle=(lower+upper)/2;
if(value==array[middle]){
index=middle;
System.out.println(value+ " found at location "+(index+1));
break;
}
else if(value<array[middle]){
upper=middle-1;
}
else lower=middle+1;
}
}
It's not too hard. We know that because the list is sorted, all of our indexes are going to be contiguous (next to one another). So once we've found one, we just have to traverse the list in both directions to find out what other indexes also match.
public static void binarySearch(int value){
sort();
int index = -1;
int lower = 0;
int upper = array.length - 1;
while(lower <= upper){
// The same as your code
}
// Create a list of indexes
final List<Integer> indexes = new LinkedList<>();
// Add the one we already found
indexes.add(index);
// Iterate upwards until we hit the end or a different value
int current = index + 1;
while (current < array.length && array[current] == value)
{
indexes.add(current);
current++;
}
// Iterate downwards until we hit the start or a different value
current = index - 1;
while (current >= 0 && array[current] == value)
{
indexes.add(current);
current--;
}
// Sort the indexes (do we care?)
Collections.sort(indexes);
for (int idx : indexes)
{
System.out.println(value + " found at " + (idx + 1));
}
}
Bear in mind that what you have implemented is already a binary search. The extra code to find additional matching indexes would not fall under the usual definition of a binary search.
Is there an Iterator to loop over data structure in cycles?
Let's say there is an array:
int[] arr = {-1,5,7,-1,-1,-1}
I want to find index of first non -1 value from this array and starting to search from the random position (idx = random.nextInt(arr.length)). For example idx = 4;
So first check if arr[4] == -1, then if arr[5] == -1 and so on. If the end of the array reached then start from 0 position and continue until non -1 found. It is guaranteed that there will be at least one value not equal to -1 in the array.
This can be done so:
int idx = -1;
for (int i = random.nextInt(arr.length); ; i++) {
if (i == arr.length) {
/** start over */
i = 0;
}
if (-1 != arr[i]) {
idx = i;
break;
}
}
Or so:
int idx = -1;
int i = random.nextInt(arr.length);
do {
if (-1 != arr[i]) {
idx = i;
}
i == arr.length ? i=0 : i++;
} while (-1 == idx);
Is there an Iterator, that supports cycling (call next() , if the end of array reached then automatically start from 0)?
Limitations: 1) efficiency is not considered; 2) standard Java API is preferred.
in java API there is no such api which satisfy your problem but you can made it by your own.
what you can do is use List to create LinkedList. to solve your problem.
you can extend List to your class (CircularLinkedList extends List) & then override method hasNext() & getNext() thats all you need.
I don't think there are any iterators that let you know the index of the element as you call next(), so you'd have to keep track of the current index separately. You might be able to build up a "wrap-around" iterator using Guava's Iterators.concat (or some other third-party class) to concatenate an iterator over the trailing part of the array with an iterator over the leading part. However, I think the code is likely to be more complex than a simple for loop or two.
I believe there is no such circular Iterator that will automatically go to the beginning of the array once the end has been reached. I have created one below (not tested, and design is flawed), which requires an entirely new class of code, and is much longer than your short for/while loops.
public class MyCircularIterator<E> implements Iterator<E> {
private List<E> list;
private int pos;
public MyCircularIterator(List<E> list) {
this(list, 0);
}
public MyCircularIterator(List<E> list, int start) {
this.list = list;
pos = start;
}
public boolean hasNext() {
if(list.get(pos) != -1) return false;
return true;
}
public E next() {
if(hasNext()) {
E obj = list.get(pos);
pos = (pos + 1) % list.size();
return obj;
}
}
public void remove() {
list.remove(this.nextIndex);
}
}
I am trying to construct a binarySearch method that goes through a sorted array, and evaluates whether a given element, given as int target, is present. It will do so by evaluating whether the mean value is greater or less than the target value, and will loop through the first or second half of the array accordingly.
I think I have the basic code down, but I am running into some problems:
int target = 0; (returns true) => correct
int target = (3, 6, 9); (returns false) => should return true
int target = (15, 19, 21, 90); returns "java.lang.ArrayIndexOutOfBoundsException: 15" => should be true
I imagine it has to do with my for statements in the respective if cases, but I have tried to debug and cannot. Also, I not permitted to use library methods.
Hopefully this question is helpful for other beginners like me. I would think it explores some java concepts like syntax, logic, and basic use Thanks for the help.
public class ArrayUtilities
{
public static void main(String[] args)
{
int[] arrayBeingSearched = {0, 3, 6, 9, 12, 15, 19, 21, 90};
int target = 90;
System.out.println("linear: " + linearSearch(arrayBeingSearched, target));
System.out.println("binary: " + binarySearch(arrayBeingSearched, target));
}
public static boolean binarySearch(int[] arrayBeingSearched, int target)
{
boolean binarySearch = false;
for (int i = 0; i < arrayBeingSearched.length; i++){
int left = 0; //array lower bound
int right = arrayBeingSearched.length - 1; //array upper bound
int middle = ((right - left) / (2)); //array mean
if(arrayBeingSearched[middle] == target){
binarySearch = true;
}
else if(arrayBeingSearched[middle] < target){
for(int j = middle + 1; j < arrayBeingSearched.length - 1; j ++){
int newLeft = arrayBeingSearched[j ++];
if(arrayBeingSearched[newLeft] == target){
binarySearch = true;
break;
}
else{
binarySearch = false;
}
}
}
else if(arrayBeingSearched[middle] > target)
for(int l = 0; l < middle - 1; l ++){
int newRight = arrayBeingSearched[l ++];
if(arrayBeingSearched[newRight] == target){
binarySearch = true;
break;
}
else{
binarySearch = false;
}
}
else{
binarySearch = false;
}
}
return binarySearch;
}
}
Okay, based on the comments, would this be a better representation? The first comment answered my question mostly but I just wanted to follow up:
public static boolean binarySearch(int[] array, int target)
{
int start = 0;
int end = array.length - 1;
while (start <= end)
{
int middle = start + (end - start)/2;
if (array[middle] == target) {
return true;
}
else if (array[middle] > target)
{
end = middle - 1;
}
else start = middle + 1;
}
return false;
}
}
This is a bad start:
for (int i = 0; i < arrayBeingSearched.length; i++)
That's a linear search, with something else within it. I haven't followed exactly what you're doing, but I think you should probably start again... with a description of binary search in front of you.
Typically a binary search loop looks something like:
int left = 0; // Inclusive lower bound
int right = arrayBeingSearch.length; // Exclusive upper bound
while (left < right) {
// Either change left, change right, or return success
// based on what you find
}
When your middle element is smaller than the target, you do this
int newLeft = arrayBeingSearched[j ++];
if(arrayBeingSearched[newLeft] == target) //...
And the equivalent when it's larger.
That is, you are taking an element of the array and using it as an index. Your array could contain only one element with a value of 1000, which is why you're running into an ArrayIndexOutOfBoundsException.
I'm sure there are other problems (see Jon's answer), but I wanted to mention that code like this:
for(int j = middle + 1; j < arrayBeingSearched.length - 1; j ++){
int newLeft = arrayBeingSearched[j ++];
will not do what you want. The for statement says that each time the program goes through the loop, it will add 1 to j (at the end of the loop code). But the next statement will use j as an index and then add 1 to it. The result is that each time you go through the loop, 1 will be added to j twice, so you're basically looking only at every other element. If this were otherwise correct (which I don't think it is), I'd say you definitely need to remove the ++ from the second line.