given a number, i was aked to find the next number which is a palindrome.Thisis the code i have writen. my code works fine but the website I am working on says "time limit exceeded"...how do I correct this?
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define MAXLEN 50
void reverse (char s[]){
int c,i,j;
for (i=0,j=strlen(s)-1;i<j;i++,j--){
c= s[i];
s[i]=s[j];
s[j]=c;
}
}
void itoa (int n, char s[]) {
int i;
i = 0;
do {
s[i++] = n % 10 + '0';
} while ((n /= 10) > 0);
s[i] = '\0';
reverse(s);
}
int main (void) {
int t,j;
scanf("%d",&t);
for(j=0;j<t;j++){
int k,c=1,i;
char s[MAXLEN];
scanf("%d",&k);
int a= k+1;
while (c!=0){
itoa(a,s);
int e=strlen(s)-1;
for(i=0;i<(e+1)/2;i++){
if (s[i]==s[e-i]){
c=0;
}
else{
c=1;
goto state;
}
}
state:a++;
}
printf("%s\n",s);
}
return 0;
}
You need to use a smarter way than brute force!
Here is an algorithm with time complexity log(N):
Read the number as a string.
Take the first half of the number.
Make a palindrome by adding the first half reversed. (Consider the two cases: even/odd length of the original number)
If this palindrome is greater than the original number you are done.
If it is not:
Take the first half of the number and add 1.
Make a palindrome by adding the first half reversed. (Again consider the two cases: even/odd length of the original number).
Done!
Related
So, I was writing this code for counting the digit frequency i.e. the number of times the digits from 0-9 has appeared in a user inputted string(alphanumeric). So, I took the string, converted into integer and tried to store the frequency in "count" and print it but when I run the code, count is never getting incremented and the output comes all 0s. Would be grateful if anyone points out in which part my logic went wrong.
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
int main() {
// takes string input
char *s;
s = malloc(1024 * sizeof(char));
scanf("%[^\n]", s);
s = realloc(s, strlen(s) + 1);
//turns the string to int
int x = atoi(s);
int temp = x, len = 0;
//calculates string length
while (x != 0) {
x = x / 10;
len++;
}
x = temp;
//parses through the string and matches digits with each number
for (int j = 0; j < 10; j++){
int count = 0;
for(int i = 0; i < len; i++){
if(x % 10 == j){
count++;
}
x = x / 10;
}
x = temp;
printf("%d ", count);
}
return 0;
}
To write a correct and reasonable digit-counting program:
Do not allocate any buffer for this.
Create an array to count the number of times each digit occurs. The array should have ten elements, one for each digit.
Initialize the array to zero in each element.
In a loop, read one character at a time.
Leave the loop when the read routine (such as getchar) indicates end-of-file or a problem, or, if desired, returns a new-line or other character you wish to use as an end-of-input indication.
Inside the loop, check whether the character read is a digit. If the character read is a digit, increment the corresponding element of the array.
After the loop, execute a new loop to iterate through the digits.
Inside that loop, for each digit, print the count from the array element for that digit.
Your approach is way to complicated for a very easy task. This will do:
void numberOfDigits(const char *s, int hist[10]) {
while(*s) {
if(isdigit(*s))
hist[*s - '0']++;
s++;
}
}
It can be used like this:
int main(void) {
char buf[1024];
int hist[10];
fgets(buf, sizeof buf, stdin);
numberOfDigits(s, hist);
for(int i=0; i<10; i++)
printf("Digit %d occurs %d times\n", i, hist[i]);
}
This can also be quite easily achieved without a buffer if desired:
int ch;
int hist[10];
while((ch = getchar()) != EOF) {
if(isdigit(ch))
hist[ch - '0']++;
}
#include <stdio.h>
int main(void) {
int input = 1223330;
int freq[10] = {0};
input = abs(input);
while(input)
{
freq[input%10]++;
input /= 10;
}
for(int i=0; i<10; ++i)
{
printf("%d: %.*s\n", i, freq[i], "*************************************************");
}
return 0;
}
Output:
Success #stdin #stdout 0s 5668KB
0: *
1: *
2: **
3: ***
4:
5:
6:
7:
8:
9:
This app is currently limited by the size of an int (approximately 9 or 10 digits).
You can update it to use a long long easily, which will get you to about 19 digits.
I am solving this problem:
Given a string str containing alphanumeric characters, calculate sum
of all numbers present in the string.
Input:
The first line of input contains an integer T denoting the number of test cases. Then T test
cases follow. Each test case contains a string containing alphanumeric characters.
Output:
Print the sum of all numbers present in the string.
Constraints:
1 <= T<= 105
1 <= length of the string <= 105
Example:
Input:
4
1abc23
geeks4geeks
1abc2x30yz67
123abc
Output:
24
4
100
123
I have come up with the following solution:
#include <stdio.h>
#include <string.h>
int main() {
//code
int t,j;
char a[100000];
scanf("%d",&t);
while(t--)
{
int sum=0,rev=0,i=0,l;
scanf("%s",a);
l=strlen(a);
for(i=0;i<l;i++)
{
if (isdigit(a[i])){
while(isdigit(a[i])){
rev = rev *10 + (a[i]-48);
i++;
}
}
sum+=rev;
rev=0;
}
printf("%d\n",sum);
}
return 0;
}
This code is working fine.
BUT if loop termination condition is changed from i < l to a[i]!='\0', then code doesn't work. Why?
I would loop backwards over the string. No nested loops. Just take the 10s exponent as you move left
You have the length of the string, so there should be no reason to check for NUL char yourself
(untested code, but shows the general idea)
#include <math.h>
l=strlen(a);
int exp;
exp = 0;
for(i = l-1; i >= 0; i--)
{
if (isdigit(a[i])) {
rev = a[i]-48; // there are better ways to parse characters to int
rev = (int) pow(10, exp) * rev;
sum += rev; // only add when you see a digit
} else { exp = -1; } // reset back to 10^0 = 1 on next loop
exp++;
}
Other solutions include using regex to split the string on all non digit characters, then loop and sum all numbers
You will have to change the logic in your while loop as well if you wish to change that in your for loop condition because it's quite possible number exists at the end of the string as well, like in one of your inputs 1abc2x30yz67. So, correct code would look like:
Snippet:
for(i=0;a[i]!='\0';i++)
{
if (isdigit(a[i])){
while(a[i]!='\0' && isdigit(a[i])){ // this line needs check as well
rev = rev *10 + (a[i]-48);
i++;
}
}
sum+=rev;
rev=0;
}
On further inspection, you need the condition of i < l anyways in your while loop condition as well.
while(i < l && isdigit(a[i])){
Update #1:
To be more precise, the loop while(isdigit(a[i])){ keeps going till the end of the string. Although it does not cause issues in the loop itself because \0 ain't a digit, but a[i] != '\0' in the for loop condition let's you access something beyond the bounds of length of the string because we move ahead 1 more location because of i++ in the for loop whereas we already reached end of the string inside the inner while loop.
Update #2:
You need an additional check of a[i] == '\0' to decrement i as well.
#include <stdio.h>
#include <string.h>
int main() {
//code
int t,j;
char a[100000];
scanf("%d",&t);
while(t--)
{
int sum=0,rev=0,i=0,l;
scanf("%s",a);
l=strlen(a);
for(i=0;a[i]!='\0';i++)
{
if (isdigit(a[i])){
while(a[i] != '\0' && isdigit(a[i])){ // this line needs check as well
rev = rev *10 + (a[i]-48);
i++;
}
}
if(a[i] == '\0') i--; // to correctly map the last index in the for loop condition
sum+=rev;
rev=0;
}
printf("%d\n",sum);
}
return 0;
}
Update #3:
You can completely avoid the while loop as well as shown below:
#include <stdio.h>
#include <string.h>
int main() {
//code
int t,j;
char a[100005];
scanf("%d",&t);
while(t--)
{
int sum=0,rev=0,i=0,l;
scanf("%s",a);
l=strlen(a);
for(i=0;i<l;i++) {
if (isdigit(a[i])){
rev = rev * 10 + (a[i]-48);
}else{
sum += rev;
rev = 0;
}
}
printf("%d\n",sum + rev); // to also add last rev we captured
}
return 0;
}
Other answers have pointed out the correct loop conditions to ensure proper operation of your program.
If you are allowed to use library functions other than isdigit, I would recommend using strtol with the EndPtr parameter (output parameter that points to the character in the string that caused strtol to stop scanning a number):
char str[] = "1abc23def5678ikl";
int main()
{
char *pStop = str;
int n, accum = 0;
size_t len = strlen(str);
do
{
n = strtol(pStop, &pStop, 10);
pStop++;
if(n)
{
printf("%d\n", n);
accum += n;
}
}
while(pStop < &str[len]);
printf("Total read: %d\n", accum);
return 0;
}
Suggest some ways to reduce the time complexity of this following code.
The problem is:
This is question
This is sample input output
This code is working fine except two cases (terminated due to time limit 2s)
#include<stdio.h>
#include<string.h>
int main()
{
unsigned char str[1000000];
unsigned long int l;
int i,j,t,k,c=0;
scanf("%d",&t);
for(k=0;k<t;k++)
{
c=0;
scanf("%lu",&l);
scanf("%s",str);
for(i=0;i<l-1;i++)
{
for(j=i+1;j<l;j++)
if(str[i]=='S' && str[j]=='A')
c++;
}
printf("%d\n",c);
}
return 0;
}
I'd use the following algorithm to solve:
Traverse the string :
a variable count which will store number of S's before a currently found A and total which is the total substrings found yet.
int total=0,count=0;
for(int j=0; j < s.length(); ++j){ //s.length or till wherever you want to find
if(s[j] == 'A') total+=count;
else if(s[j]=='S') count++;
}
I wrote this small program to count the number of trailing zeroes. I got my algorithm correct. But I cannot get the output right. The first line we enter is for the number of inputs (T). Later the user enters the number (whose number of trailing zeroes in factorial is to be calculated.) And then print the answer (count). But after I input the value for N, I get the answer on the third line (I used just one '\n'). I need to get my output right.
#include <stdio.h>
int main()
{
int T;
int i,j,temp,count=0;
long int N;
scanf("%d",&T);
for(i=0;i<T;i++)
{
scanf("\n%ld",&N);
for(j=5;j<=N;j+=5)
{
temp=j;
while(j > 1)
{
if(j%5 == 0)
count++;
j=j/5;
}
j=temp;
}
printf("\n%d",count);
count =0;
}
return 0;
}
Change:
printf("\n%d",count);
to:
printf("%d\n",count);
and:
scanf("\n%ld",&N);
to:
scanf("%ld",&N);
This program takes an input of number of strings followed by the actual strings. The output should be the number of common characters to all strings.
The constraints are:
No of strings <= 100
Length of string <= 100
For example..
Input:
3
abc
bcd
cde
Output:
1
As only c is common to all strings.
It gives right output when used with small inputs.
But when used with large strings like this :https://hr-testcases.s3.amazonaws.com/2223/input19.txt?AWSAccessKeyId=AKIAINGOTNJCTGAUP7NA&Expires=1408959130&Signature=E%2BMnR6MA0gQNkuWHMvc70eCL5Dw%3D&response-content-type=text%2Fplain
It gives wrong output of 58 instead of 19.
This is my code :
#include<stdio.h>
#include<string.h>
void main(){
int n,i,j,count=0;
char s[100][100];
scanf("%d",&n);
for(i=0;i<n;i++){
scanf("%s",s[i]);
}
int t;
int l = strlen(s[0]);
for(i=0;i<l;i++){
t=0;
for(j=1;j<n;j++){
if(strchr(s[j],s[0][i])!='\0'){
t++;
}
}
if(t==n-1)
count++;
}
printf("%d",count);
}
As you iterate over the first string's characters, you might potentially find the same character more than one time.
This means that common chars found more than one time in the first string will be counted more than one time.
This is what causing your program to calculate 58 instead of 19.
Check below some quick update to your program - it treats the duplicates in the first string.
This program calculates 19 on your 100 strings' test case.
#include<stdio.h>
#include<string.h>
void main(){
int n,i,j/*,count=0*/;
int count[26] = {0}; /* counter per char */
char s[100][101];
scanf("%d",&n);
for(i=0;i<n;i++){
scanf("%s",s[i]);
}
int t;
int l = strlen(s[0]);
for(i=0;i<l;i++){
t=0;
/* convert char to integer - assuming lowercase char only */
int char_index = s[0][i] - 'a';
for(j=1;j<n;j++){
if(strchr(s[j],s[0][i])!='\0' && count[char_index] == 0){
t++;
}
}
if(t==n-1)
count[char_index] = 1;
/* count++; */
}
/* count how many chars are 1*/
int count_n = 0;
int index;
for (index = 0; index < 26; index ++)
{
if (count[index] == 1)
count_n ++;
}
printf("\n\n%d",count_n);
}