Binary search not working for n = 1, 2 - c++

This is my code for binary search, and n = no of elements in array
// Binary Search
// BUG: not working for n = 2
#include <iostream>
int main() {
const int n = 1;
int newlist[n];
std::cout << "Enter " << n;
std::cout << " elements in increasing order:\n";
for( int i = 0; i < n; ++i ) {
std::cin >> newlist[i];
}
int pos = 0, num;
std::cout << "Enter number:\n";
std::cin >> num;
std::cout << '\n';
int imin = 0, imax = n-1;
int imid = (n - 1)/2;
for( int i = 0; i < n; ++i ) {
imid = (imin + imax) / 2;
if( newlist[imid] == num ) {
pos = imid;
}
else if( newlist[imid] < num ) {
imin = imid+1;
}
else {
imax = imid-1;
}
}
if( pos != 0 ) {
std::cout << "Found at " << pos+1;
}
else {
std::cout << "Not found!\n";
}
return 0;
}
It does work for n > 2, but fails to give correct output for n <= 2, ie, gives Not found! output even for elements that were found.
I think one way would be to have a separate implementation for n <= 2, but that will become cumbersome! Please help.

Set your pos operator to -1 rather than 0. 0 represents your first index and since you output that the element has not been found for pos == 0 condition, your code is failing. You should set pos to -1 initially and check that itself for not found condition, if an element is found at pos = 0, that means the element exists at the first index.

First pos equal to 0 is correct value. Therefore set pos to -1 at the beginning and compare to -1 (or more commonly >= 0) when checking whether it was found.
Secondly, there are few items that should be changed because right now it's not that much binary search:
There is no reason to initialize mid before the loop, it's just temporary variable with the scope in loop block.
The condition for exiting the search is min > max, you don't need any additional counter, as it would run the loop always n times even if the value didn't exist. So change to while (min <= max) { ...
Last but not least, once you find the item, exit the loop immediately by break statement.

I don't think a for-loop is the control structure to go for here, because you want to finish when you've either found the correct item or when imin and imax are non-sensical.
In the implementation given, you don't even stop the loop when you have found the item and just confirm the found item "n-(number of iterations until item was found)" times.
Furthermore, with C++ arrays and vectors being 0-based, having position == 0 as the marker for "not found" is a bad idea; you could instead use an item from http://en.cppreference.com/w/cpp/types/numeric_limits, or n (since the indices go from 0 to n-1).
In theory, you could use pointer arithmetic to make your array 1-based, and I am assuming you haven't; I wouldn't recommend it. However, you're code snipped is missing the actual definition of the list.

Related

Prevent loop from echoing if another same-value array element has been already echoed in C++

First of all, sorry for the mis-worded title. I couldn't imagine a better way to put it.
The problem I'm facing is as follows: In a part of my program, the program counts occurences of different a-zA-Z letters and then tells how many of each letters can be found in an array. The problem, however, is this:
If I have an array that consists of A;A;F;A;D or anything similar, the output will be this:
A - 3
A - 3
F - 1
A - 3
D - 1
But I am required to make it like this:
A - 3
F - 1
D - 1
I could solve the problem easily, however I can't use an additional array to check what values have been already echoed. I know why it happens, but I don't know a way to solve it without using an additional array.
This is the code snippet (the array simply consists of characters, not worthy of adding it to the snippet):
n is the size of array the user is asked to choose at the start of the program (not included in the snippet).
initburts is the current array member ID that is being compared against all other values.
burts is the counter that is being reset after the loop is done checking a letter and moves onto the next one.
do {
for (i = 0; i < n; i++) {
if (array[initburts] == array[i]) {
burts++;
}
}
cout << "\n\n" << array[initburts] << " - " << burts;
initburts++;
burts = 0;
if (initburts == n) {
isDone = true;
}
}
while (isDone == false);
Do your counting first, then loop over your counts printing the results.
std::map<decltype(array[0]), std::size_t> counts;
std::for_each(std::begin(array), std::end(array), [&counts](auto& item){ ++counts[item]; });
std::for_each(std::begin(counts), std::end(counts), [](auto& pair) { std::cout << "\n\n" << pair.first << " - " pair.second; });
for (i = 0; i < n; i++)
{
// first check if we printed this character already;
// this is the case if the same character occurred
// before the current one:
bool isNew = true;
for (j = 0; j < i; j++)
{
// you find out yourself, do you?
// do not forget to break the loop
// in case of having detected an equal value!
}
if(isNew)
{
// well, now we can count...
unsigned int count = 1;
for(int j = i + 1; j < n; ++j)
count += array[j] == array[i];
// appropriate output...
}
}
That would do the trick and retains the array as is, however is an O(n²) algorithm. More efficient (O(n*log(n))) is sorting the array in advance, then you can just iterate over the array once. Of course, original array sequence gets lost then:
std::sort(array, array + arrayLength);
auto start = array;
for(auto current = array + 1; current != array + arrayLength; ++current)
{
if(*current != *start)
{
auto char = *start;
auto count = current - start;
// output char and count appropriately
}
}
// now we yet lack the final character:
auto char = *start;
auto count = array + arrayLength - start;
// output char and count appropriately
Pointer arithmetic... Quite likely that your teacher gets suspicious if you just copy this code, but it should give you the necessary hints to make up your own variant (use indices instead of pointers...).
I would do it this way.
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main()
{
string s;
vector<int> capCount(26, 0), smallCount(26, 0);
cout << "Enter the string\n";
cin >> s;
for(int i = 0; i < s.length(); ++i)
{
char c = s.at(i);
if(c >= 'A' && c <= 'Z')
++capCount[(int)c - 65];
if(c >= 'a' && c <= 'z')
++smallCount[(int)c - 97];
}
for(int i = 0; i < 26; ++i)
{
if(capCount[i] > 0)
cout << (char) (i + 65) << ": " << capCount[i] << endl;
if(smallCount[i] > 0)
cout << (char) (i + 97) << ": " << smallCount[i] << endl;
}
}
Note: I have differentiated lower and upper case characters.
Here's is the sample output:
output

Not sure where this infinite loop is coming from

I'm coming from C into C++, I might be missing something very basic.
I'm trying to make a program with the collatz conjecture.
Before the first iteration of the loop, i and j both correctly equal 1 and 10.
However, the value of i never seems to change although I have i++ in my loop.
I thought this would be a quick program to code but I'm getting hung up on this. Any help would be appreciated.
int n, j, i, count = 0;
cin >> n >> j;
for (i = n; i < j; i++){
while (i != 1){
if (i % 2 == 0)
i = i/2;
else
i = 3*i + 1;
}
count++;
cout << i << endl;
}
The problem in your code is that after you've run the while loop that tests whether the conjecture is true for i, i is by definition set back to 1 (since that's the condition to get out of the loop), so i++ keeps incrementing from 1 to 2 each time. You'll never get past 2.
If you're trying to test the Collatz Conjecture for all the numbers from n to j, you need to use a different variable in the while loop than you use for iteration.
And if count is supposed to tell you how many cycles are needed, you need to zero it before each while loop, and increment it inside the while loop.
int n, j, i;
cin >> n >> j;
for (i = n; i < j; i++){
int test = i;
int count = 0;
while (test != 1){
if (test % 2 == 0) {
test = test/2;
} else {
test = 3*test + 1;
}
count++;
}
cout << i << ' ' << count << endl;
}
Not sure what it's all about, but here's some quick observation:
your while(i != 1) loop means that it will either run indefinetely, or when this loop ends i will be equal to 1. Which means that your for (i = n; i < j; i++){ loops will always restart with i=1. No wonder it's a dead loop.
Before the first iteration of the loop, i and j both correctly equal 1 and 10.
The let's replay the second iteration of the outer loop.
Before it, at the end of the first iteration, i has been incremented to equal 2. Now,
i % 2 == 0 => i := i / 2, i.e. i := 1.
Now i == 1, inner loop ends.
i is incremented and now equals 2.
Repeat.
You can simply copy the loop variable to a new variable in every loop iteration i = k in this case, so that the for loop variable is not affected
#include <iostream>
int main(){
int min, max, count = 0;
std::cin >> min >> max;
for (int k = min; k <= max; ++k){
i = k;
while (i != 1)
{
if (i % 2 == 0)
i /= 2;
else
i = 3*i + 1;
count++;
std::cout << i << std::endl; //ONLY IF U WANT TO PRINT i EVERY ITERATION
}
std::cout << "Number of iterations needed: " << count << " for i = " << i << std:: endl;
}

Finding the Mode C++

How can I edit this function to find multiple modes? Right now if there are multiple, it will display the smallest.
Example
Input 5 5 2 2
Output 5 2
What it actually does
Input 5 5 1 1
Output 1
void calculateMode(int array[], int big)
{
int counter = 1;
int max = 0;
int mode = array[0];
for (int pass = 0; pass < big - 1; pass++)
{
if ( array[pass] == array[pass+1] )
{
counter++;
if ( counter > max )
{
max = counter;
mode = array[pass];
}
} else
counter = 1; // reset counter.
}
cout << "The mode is: " << mode << endl;
}
Anything helps!
I like also the stdlib option as one of the comments refers. However, I tried to solve this problem without using it as you (as an exercise). I had as a requirement to have a constant array as a function parameter, so I could not order it (nor remove the constant nor copy it in a new non-const one). In addition, if there are multiple modes or no elements, I had to return zero.
At the end a came up with something like the following. Hopefully, it might help.
#include <iostream>
#include <stdexcept>
template <typename T> T mode(const T *values, size_t length) {
// check if it has zero length
if (!length)
return 0;
if (!values)
throw std::invalid_argument{"Invalid input array"};
int count{}, maxOccurrences{};
int multipleModes{};
T mode{};
// check every element unless the mode's occurrences are greater than the
// remaining list
for (int k{}; k < length && maxOccurrences <= (length - k); ++k) {
// reset the count for every individual element
count = 0;
// count the number of occurrences
for (int i{}; i < length; ++i) {
if (values[k] == values[i])
count++;
}
if (count > maxOccurrences && mode != values[k]) {
mode = values[k];
maxOccurrences = count;
multipleModes = 0;
/*std::cout << "Count:" << count << " - MaxOccur:" << maxOccurrences
<< " - Mode:" << mode << std::endl;*/
}
if (count == maxOccurrences && mode != values[k]) {
// if the array has multiple modes
multipleModes = 1;
}
}
if (multipleModes == 1)
return 0;
else
return mode;
}
Thanks for you attention!
you can try adding this
else if (counter==max){
mode += array[pass]
}
can't test it on my own system. see if it's of any help.

Binary Search in 2D Array 3

I need to find a number in the 2D array.
Columns are sorted (from smallest value to the biggest).
Here is my code:
const int SIZE = 4;
const int NOT_FOUND = 1;
int binarySearch(int mat[][SIZE], int &line , int num);
void main()
{
int num, index, mat[SIZE][SIZE] = { 11,1,5,11,
11,6,7,2,
8,7,7,7,
0,12,9,10 };
int line = sizeof(mat) / sizeof(mat[0][0]);
cout << "please type a number to search: " << endl;
cin >> num;
index = binarySearch(mat, line, num);
if (index == NOT_FOUND) {
cout << "The value: " << num << "doesn't exist in the array\n";
}
else {
cout << "The value: " << num << " exists in line " << line+1
<<" and column: " << index+1 << endl;
}
system("pause");
}
int binarySearch(int mat[][SIZE], int &line, int num)
{
for (int j = 0; j < SIZE; j++)
{
int low = 0;
int high = SIZE - 1;
int middle;
while (low <= high)
{
middle = (low + high) / 2;
if (num == mat[middle][j])
{
line = middle;
return j;
}
else if (num < mat[middle][j]) {
high = middle - 1;
{
else {
low = middle + 1;
}
}
}
return NOT_FOUND;
}
The program doesn't find all the numbers in the array.
Something doesn't work.
What is the problem?
Your binarySearch doesn't go through all the numbers, it checks the first number, so in your case 11, then it moves to the next number, but it skips the whole row of numbers (1, 5, 11) and the first number in second row and then moves to the next second number which will be 6 in second row.
Since you have a Matrix of number it consists of Rows and Columns, that means you have to create two loops for(...), once for the Rows and one for the Columns so you can go through all the numbers in your 2D array.
I recommend setting a Break point on the binarySearch function and going through with that, it'll help you a lot.
A few things that I see wrong in your code are ::
1) It appears that you are applying binary search to every column in your input array, and if the number is not found in the corresponding column, you increment j and move to the next column.
The most important thing about binary search is "The array in which you are searching should always be sorted". Since here you are searching columns, all your columns shall be sorted! Which appears unsorted in the code above! Which is a major reason why you don't find most elements. So, your input array shall look something like this (if you want to apply binary search) ::
int mat[SIZE][SIZE] = { 0,1,5,2,
8,6,7,7,
11,7,7,10,
11,12,9,11 }
All columns sorted in ascending order here!
2) The value of the variable NOT_FOUND you have set it to 1 and from your function you return the column number from where you found the element. So, if you found the element in the 2D array in column 1 your program will print Element Not Found because the condition if (index == NOT_FOUND) evaluates to true if the element was found in column 1. So, a better solution would be to change the value of NOT_FOUND to some negative value, since it can never be the column number in a valid case. Something like this ::
const int NOT_FOUND = -1;
Ideone link of code :: http://ideone.com/9cwHnY

finding minimum number of jumps

Working on below algorithm puzzle of finding minimum number of jumps. Posted detailed problem statement and two code versions to resolve this issue. I have did testing and it seems both version works, and my 2nd version is an optimized version of version one code, which makes i starts from i=maxIndex, other than continuous increase, which could save time by not iteration all the slots of the array.
My question is, wondering if my 2nd version code is 100% correct? If anyone found any logical issues, appreciate for pointing out.
Problem Statement
Given an array of non-negative integers, you are initially positioned at the first index of the array.
Each element in the array represents your maximum jump length at that position.
Your goal is to reach the last index in the minimum number of jumps.
For example:
Given array A = [2,3,1,1,4]
The minimum number of jumps to reach the last index is 2. (Jump 1 step from index 0 to 1, then 3 steps to the last index.)
First version code
class Solution {
public:
int jump(vector<int>& nums) {
int i = 0, n = nums.size(), step = 0, end = 0, maxend = 0;
while (end < n - 1) {
step++;
for (;i <= end; i++) {
maxend = max(maxend, i + nums[i]);
if (maxend >= n - 1) return step;
}
if(end == maxend) break;
end = maxend;
}
return n == 1 ? 0 : -1;
}
};
2nd version code
class Solution {
public:
int jump(vector<int>& nums) {
int i = 0, n = nums.size(), step = 0, end = 0, maxend = 0;
int maxIndex = 0;
while (end < n - 1) {
step++;
for (i=maxIndex;i <= end; i++) {
if ((i + nums[i]) > maxend)
{
maxend = i + nums[i];
maxIndex = i;
}
if (maxend >= n - 1) return step;
}
if(end == maxend) break;
end = maxend;
}
return n == 1 ? 0 : -1;
}
};
thanks in advance,
Lin
The best way is always to test it. A human cannot always think about special cases but a automated test can cover the most of speciale cases. If you think that your first version works well, you can compare the result of the first with the second one. Here an exemple:
/*
* arraySize : array size to use for the test
* min : min jump in the array
* max : max jump in the array
*/
void testJumps(int arraySize, int min, int max){
static int counter = 0;
std::cout << "-----------Test " << counter << "------------" << std::endl;
std::cout << "Array size : " << arraySize << " Minimum Jump : " << min << " Max Jump" << max << std::endl;
//Create vector with random numbers
std::vector<int> vecNumbers(arraySize, 0);
for(unsigned int i = 0; i < vecNumbers.size(); i++)
vecNumbers[i] = rand() % max + min;
//Value of first function
int iVersion1 = jump1(vecNumbers);
//Second fucntion
int iVersion2 = jump2(vecNumbers);
assert(iVersion1 == iVersion2);
std::cout << "Test " << counter << " succeeded" << std::endl;
std::cout << "-----------------------" << std::endl;
counter++;
}
int main()
{
//Two test
testJumps(10, 1, 100);
testJumps(20, 10, 200);
//You can even make a loop of test
//...
}