Difference between flow of if....if block and if....else block - if-statement

So I was just solving this question the previous day
https://leetcode.com/problems/search-a-2d-matrix-ii/
I was able to solve the problem....but was confused in the execution of if...else block vs if...if block.
The if...else block didn't give me any error while the if....if block gave me an error of IndexOutOfBoundException for length = 1.
Can someone please tell me what's the difference in Layman's term and what am I doing wrong here?
Here is my code ---->
class Solution {
public boolean searchMatrix(int[][] m, int target) {
int x =m.length;
int n= m[0].length;
int i = 0 , j=n-1;
while(i<x && j>=0){
if(m[i][j]==target){
return true;
}
if(m[i][j]>target){
j--;
}
if(m[i][j]<target) {
i++;
}
}
return false;
}
}
************************************* VS ******************************************
class Solution {
public boolean searchMatrix(int[][] m, int target) {
int x =m.length;
int n= m[0].length;
int i = 0 , j=n-1;
while(i<x && j>=0){
if(m[i][j]==target){
return true;
}
if(m[i][j]>target){
j--;
}
else {
i++;
}
}
return false;
}
}

One issue is that this can take you off the bottom of your matrix if j=0.
if(m[i][j]>target){
j--;
}
if(m[i][j]<target) {
i++;
Let's say m[3][0] > target, and you subtract 1 from j, giving j=-1. In your if-else solution, the else is skipped, the while loop then sees that j<0, and the loop exits. Fine.
But in your if-if solution, it then executes if(m[3][-1]<target), which causes the IndexOutOfBoundException
There may be other scenarios too - I haven't checked.

Related

C++ runtime error: addition of unsigned offset?

I wrote the following to check if text is palindrome, I run it on leetcode and I am getting errors:
class Solution {
public:
bool isPalindrome(string s) {
int l=0,r=s.length()-1;
while(l<r)
{
while (!isalpha(s[r]))
{
--r;
}
while (!isalpha(s[l]))
{
++l;
}
if (tolower(s[r])!=tolower(s[l]))
return false;
--r;
++l;
}
return true;
}
};
Line 1061: Char 9: runtime error: addition of unsigned offset to
0x7ffc7cc10880 overflowed to 0x7ffc7cc1087f (basic_string.h) SUMMARY:
UndefinedBehaviorSanitizer: undefined-behavior
/usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/bits/basic_string.h:1070:9
what's the problem with my code?
You're going out of bounds here:
while (!isalpha(s[r]))
and here
while (!isalpha(s[l]))
r can became negative and l can become >= s.length().
You should add some checks like
while (l < r && !isalpha(s[r]))
and
while (l < r && !isalpha(s[l]))
The same problem in this line
if (tolower(s[r])!=tolower(s[l]))
This should be
if (l < r && tolower(s[r])!=tolower(s[l]))
Different approach (C++20)
A different approach is to erase all non-alpha characters from s with
std::erase_if(s, [](char c) { return !isalpha(c); });
and remove the inner while loops.
I think you were very close to the solution. The pitfall here are that:
you are modifying the loop control variable more than once in the loop
(as consequence) you are using the loop control variable after changing their values without further checks.
The easy way to fix this kind of issue is to do one single action for every iteration. you can achieve this just using "else".
class Solution {
public:
bool isPalindrome(string s) {
int l=0,r=s.length()-1;
while(l<r)
{
if(!isalpha(s[r]))
{
--r;
}
else if(!isalpha(s[l]))
{
++l;
}
else if (tolower(s[r])!=tolower(s[l]))
{
return false;
}
else
{
--r;
++l;
}
}
return true;
}
};

Find next largest palindrome number

I wrote the following program to find the nearest largest palindrome for each of the entered numbers. The first line gives input of how many integers are to be entered.
My problem is I've tried with test cases on geekforgeeks and spojtoolkit (also random numbers whose nearest palindrome I know) and am getting the right answer. SPOJ however says wrong answer. Can anyone suggest cases where my code may not work or possible corrections in my code.
using namespace std;
void evenmirror(char g[1000000],int n)
{
int k=n/2;
for(int i=n/2-1;i>=0;i--)
{
g[k]=g[i];
k++;
}
cout<<g;
}
void oddmirror(char g[1000000],int n)
{
int k=n/2+1;
for(int i=n/2-1;i>=0;i--)
{
g[k]=g[i]; k++;
}
cout<<g;
}
int main()
{
int n,i,j,m;
char g[1000000];
cin>>m;
for(int t=0;t<m;t++)
{
cin>>g;
n=strlen(g);
if(n==1 && g[0]!='9'){cout<<++g[0]; continue;}//single digits except9
int s=0;
int h=0;
if(g[0]=='9' && g[n-1]=='9')
{
for(i=0;i<n;i++)
{
if(g[i]=='9') {h++; }
}
if(h==n)
{
for(i=0;i<=n;i++)
{
if(i==0 || i==n) { cout<<1;}
else {cout<<0;}
}
s=1;
}
}
if(n%2==0 && s==0)
{
i=n/2-1; j=n/2;
while(g[i]==g[j] && i>0)
{
i--; j++;
if(i==0){break;}
}
//if palindrome
if(j==n-1 && g[j]==g[i])
{
if(g[n/2-1]<'9'){ g[n/2-1]++; }
else if(g[n/2]=='9'){(g[n/2-1])='0'; g[n/2-2]+=1;}
evenmirror(g,n);
}//if even string is not palindrome
else
{
if(g[i]<g[j])
{
if(g[n/2-1]<'9'){ g[n/2-1]++; }
else if(g[n/2]=='9'){ g[n/2-1]='0'; g[n/2-2]+=1;}
evenmirror(g,n);
}
else{ evenmirror(g,n); }
}
}
//if odd number string
else if(n%2!=0 && s==0)
{
i=(n/2)-1; j=(n/2)+1;
while(g[i]==g[j] && i>0)
{
i--; j++;
}
//if palindrome
if(j==n-1 && g[j]==g[i])
{
if(g[n/2]<'9'){ g[n/2]++; }
else if(g[n/2]=='9'){ g[n/2]='0'; g[n/2-1]+=1;}
oddmirror(g,n);
}//if odd not palindrome
else
{
char k=n/2+1;
if(g[i]<g[j])
{
if(g[n/2]<'9'){ g[n/2]++; }
else if(g[n/2]=='9'){(g[n/2])='0'; g[n/2-1]+=1;}
oddmirror(g,n);
}
else{ oddmirror(g,n); }
}
}
cout<<endl;
}
return 0;
}
Here is the question: http://www.spoj.com/problems/PALIN/
I didn't debug your code (you didn't ask for it and I think that it should be done by you anyway) but for the following input I got wrong answer:
Input: 9 (expected output 11)
Output: :
Good luck fixing it :)
Since this is an algorithm question, I'll try to keep it language neutral.
The simple way to find the next palindrome is to keep testing until you find one, stepping up one at a time. This is simply a loop, incrementing one at a time and testing.
The test for a palindrome is quite simple. I think you've overcomplicated it by splitting it into odd and even cases. You can either turn the number into a string and check the reverse() is the same, which is neat and tidy (because it's inside a call), but takes memory, or you can do it in place using two pointers. One pointer at the beginning of the string, and one at the end, each moving towards the middle, with the condition being they have to show the same character as the other, and the loop ending when they both point to the middle, or the have switched relative positions.

SPOJ: What is the difference between these two answers for KURUK14

I have solved this problem and got AC. My problem is related to equivalence of following two approaches. The first code got accepted, while the second didn't.
As far as I can discern, both are completely equivalent for all the (valid) test cases any human can think of. Am I wrong? If so, what test case can differentiate them?
Code#1 (Accepted one):
#include <cstdio>
bool* M;
bool proc(int N){
for(int j=0;j<=N;j++){
M[j]=false;
}
for(int i=0;i<N;i++){
int a=0;
scanf("%d",&a);
if(a>=N)
return false;
else if(!M[a])
M[a]=true;
else if(!M[N-1-a])
M[N-1-a]=true;
}
bool f = true;
for(int k=0;k<N;k++)
{
f = f && M[k];
}
return f;
}
int main() {
M=new bool[1002];
int num=0;
scanf("%d",&num);
while(num){
int N=0;
scanf("%d",&N);
if(proc(N))
printf("YES\n");
else
printf("NO\n");
num--;
}
return 0;
}
Code #2 (WA):
#include <cstdio>
bool* M;
bool proc(int N){
for(int j=0;j<=N;j++){
M[j]=false;
}
for(int i=0;i<N;i++){
int a=0;
scanf("%d",&a);
if(a>=N)
return false;
else if(!M[a])
M[a]=true;
else if(!M[N-1-a])
M[N-1-a]=true;
else
return false;
}
return true;
}
int main() {
//Exactly same as code#1
}
The bug has nothing to do with the algorithm itself—it's very possible both the algorithms are correct. But the second implementation is wrong.
When you reach a test case which should return NO, you exit the function prematurely. Which means there are some numbers from the current test case left unread in the input, which of course confuses further reading thoroughly. This means the bug only manifests when T > 1.

Error: not all control paths return a value

I am writing two functions in a program to check if a string has an assigned numeric code to its structure array or if the given numeric code has an assigned string in the same structure array. Basically, if I only know one of the two, I can get the other. I wrote the following:
int PrimaryIndex::check_title_pos(std::string title) {
bool findPos = true;
if (findPos) {
for (int s = 1; s <= 25; s++) {
if (my_list[s].title == title) {
return s;
}
}
} else {
return -1;
}
}
std::string PrimaryIndex::check_title_at_pos(int pos) {
bool findTitle = true;
if (findTitle) {
for (int p = 1; p <= 25; p++) {
if (my_list[p].tag == pos) {
return my_list[p].title;
}
}
} else {
return "No title retrievable from " + pos;
}
}
However, it says not all control paths have a return value. I thought the else {} statement would handle that but it's not. Likewise, I added default "return -1;" and "return "";" to the appropriate functions handling int and string, respectively. That just caused it to error out.
Any idea on how I can keep this code, as I'd like to think it works but cant test it, while giving my compiler happiness? I realize through other searches that it sees conditions that could otherwise end in no returning values but theoretically, if I am right, it should work fine. :|
Thanks
In the below snippet, if s iterates to 26 without the inner if ever evaluating to true then a return statement is never reached.
if (findPos) {
for (int s = 1; s <= 25; s++) {
if (my_list[s].title == title) {
return s;
}
}
}

How to break out of a while loop with a boolean?

I am trying to break out of several nested while loops and I am having trouble. I want this program to break out into the outer loop, which will run only a certain amount of times. I tried doing it with a boolean but my program terminates too early. It is an N-Queens problem where I am solving for 1x1, 2x2, 3x3,...nxn queens.
Here is my code:
bool ok(int *q, int col)
{
for(int i=0; i<col; i++)
if(q[col]==q[i] || (col-i)==abs(q[col]-q[i])) return false;
return true;
};
void print(int q[], int n, int cnt)
{
//static int count =0;
cout<<"There are "<<cnt<<" solutions for "<<n<<" queens." <<endl;
};
int main()
{
int n;
int *q;
cout<<"Please enter the size of the board:"<<endl;
cin>>n;
int static count = 0;
int c = 1;
int a = 1;
bool from_backtrack=false;
while(a!=n){
q= new int[a];
q[0]=0;
bool foundSolution=true;
while(foundSolution)
{
if (c==a){
a++;
}
while(c<a)
{
if(!from_backtrack)
q[c] = -1; //Start at the top
from_backtrack=false;
while(q[c]<a)
{
q[c]++;
if (q[c]==a)
{
c--;
if(c==-1) {
print(q, n, count);
foundSolution=false;
//system("PAUSE"); exit(1);
}
continue;
}
if( ok(q,c) ) break; //get out of the closest while loop
}
c++;
}
count++;
c--;
if(c==-1) {
print(q, n, count);
foundSolution=false;
//system("PAUSE"); exit(1);
}
from_backtrack=true;
}
delete[a] q;
a++;
}
system("PAUSE");
}
The most elegant way would be to wrap some of your inner loops in a function.
It will be easier to read and to control.
At my work, we employ MISRA guidelines which state "... only 1 break per while loop". This has caused me to rewrite my if and while loops:
bool can_continue = true;
if (can_continue)
{
status = Do_Something();
if (status != SUCCESS)
{
can_continue = false;
}
}
if (can_continue)
{
status = Do_Another_Thing();
can_continue = status == SUCCESS;
}
//.. and so on.
The idea is to set a flag to "false" if execution can't continue. Check it after any segment can cause execution to fail.
while( true ){
if( condition == true ){
goto bye;
}
}
:bye
Just don't submit this on your homework...
Think it is as crazy as useless.
However, suppose you want 3 iterations, you'll define an array of bool of 3 elements (all set to true). On each iteration you set the current element to false, until you reach the end of your array.