My output have an extra 0 in it, why is that - c++

So I'm doing practice on leetcode and this is the question:
You are given two non-empty linked lists representing two non-negative
integers. The digits are stored in reverse order and each of their nodes
contain a single digit. Add the two numbers and return it as a linked list.
You may assume the two numbers do not contain any leading zero, except the
number 0 itself.
Example:
Input: (2 -> 4 -> 3) + (5 -> 6 -> 4)
Output: 7 -> 0 -> 8
Explanation: 342 + 465 = 807.
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
And this is my solution:
class Solution {
public:
ListNode *addTwoNumbers(ListNode *l1, ListNode *l2) {
vector<int> V1;
vector<int> V2;
int sum1 = 0;
int sum2 = 0;
ListNode *result = new ListNode(0);
auto l0 = result;
while(l1) {
V1.push_back(l1->val);
l1=l1->next;
}
for (auto it1 = V1.rbegin(); it1 != V1.rend(); it1++) {
sum1 = sum1 * 10 + (*it1);
}
while(l2) {
V2.push_back(l2->val);
l2=l2->next;
}
for (auto it2 = V2.rbegin(); it2 != V2.rend(); it2++) {
sum2 = sum2 * 10 + (*it2);
}
int sum3 = sum1 + sum2;
while (sum3 !=0) {
int extract = sum3 % 10;
l0->next = new ListNode(extract);
sum3 /= 10;
l0=l0->next;
}
return result;
}
};
And when I ran it, there is always and extra 0 in my output, for example:
Your input
[7,2,7] [2,4,2]
Your answer
[0,9,6,9]
Expected answer
[9,6,9]
I know there is a smarter way to solve this question, but I want to try to solve it in my way first

Its because you are creating the first node with 0. You have two solutions for that:
Skip the first element at the end of the function (workaround):
ListNode* aux = result;
result = result->next;
delete aux;
return result;
Not initialize the listnode to zero, use a nullpointer instead:
s
ListNode *result = nullptr;
// More code...
while (sum3 !=0) {
int extract = sum3 % 10;
if (l0 == nullptr) {
result = new ListNode(extract);
l0 = result;
}
else
l0->next = new ListNode(extract);
sum3 /= 10;
l0=l0->next;
}
Ofc, there are better solutions. You could do the sum directly, without using extra vectors/memory.

You are getting an extra zero because you are doing remainder and division operation 1 time extra than required. You have to modify the condition under last while loop.
while (sum3 > 9) {
int extract = sum3 % 10;
l0->next = new ListNode(extract);
sum3 /= 10;
l0=l0->next;
}

Related

Outputs get changed after removing one printing statement

#include <iostream>
//Definition for singly-linked list.
struct ListNode {
int val;
ListNode *next;
ListNode() : val(0), next(nullptr) {}
ListNode(int x) : val(x), next(nullptr) {}
ListNode(int x, ListNode *next) : val(x), next(next) {}
};
class Solution {
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2)
{
ListNode *final_ll;
ListNode **ptr_final = &final_ll;
int carry, sum;
while (l1!=NULL || l2!=NULL || carry > 0)
{
int s1 = ((l1!=NULL) ? l1->val: 0);
int s2 = ((l2!=NULL) ? l2->val: 0);
sum = s1 + s2 + carry;
carry = sum / 10;
(*ptr_final) = new ListNode(sum % 10);
//std::cout << "tenth_digit = " << carry << std::endl;
std::cout << "unit_digit = " << sum % 10 << std::endl;
if (l1!=NULL) l1 = l1->next;
if (l2!=NULL) l2 = l2->next;
ptr_final = &((*ptr_final)->next);
}
return final_ll;
}
};
int main() {
ListNode l1(9);
ListNode l2(8, &l1);
ListNode *result = Solution().addTwoNumbers(&l1, &l2);
}
This code outputs:
unit_digit = 5
unit_digit = 1
unit_digit = 1
However, when I uncomment
std::cout << "tenth_digit = " << carry << std::endl;
In Solution class, outputs are changed to:
tenth_digit = 3278
unit_digit = 4
tenth_digit = 328
unit_digit = 7
tenth_digit = 32
unit_digit = 8
tenth_digit = 3
unit_digit = 2
tenth_digit = 0
unit_digit = 3
A single printing statement should not change the number of iterations of the while loop and the value of unit_digit during each iteration. What's happening here?
Your code has undefined behavior.
In addTwoNumbers(), the final_ll and carry variables are both uninitialized, and both are being used before they have been assigned valid values.
carry holds a random value when declared, throwing off your while loop if that value is not 0.
If l1 and l2 were nullptr, and carry happened to be randomly <= 0, the body of the while loop would not be entered at all, causing addTwoNumbers() to return an indeterminate ListNode* value to the caller. And if carry were randomly > 0 instead, your while loop would run more times than you intend, skewing the results.
You need to initialize both variables, eg:
ListNode *final_ll = nullptr;
...
int carry = 0;
I would also suggest moving the declaration of sum inside the loop, since its value does not need to be preserved across loop iterations:
int carry = 0;
while (l1 || l2 || carry > 0)
{
...
int sum = s1 + s2 + carry;
...
}

How to multiply std::vector<int> by int where vector's each element should be one digit?

I have a class, call it 'BigNumber', which has a vector v field.
Each element should be one digit.
I want to implement a method to multiply this vector by an integer, but also keep elements one digit.
E.g: <7,6> * 50 = <3,8,0,0>
The vector represents a number, stored in this way. In my example, <7,6> is equal to 76, and <3,8,0,0> is 3800.
I tried the following, but this isn't good (however it works), and not the actual solution for the problem.
//int num, BigNumber bn
if (num > 0)
{
int value = 0, curr = 1;
for (int i = bn.getBigNumber().size() - 1; i >= 0; i--)
{
value += bn.getBigNumber().at(i) * num * curr;
curr *= 10;
}
bn.setBigNumber(value); //this shouldn't be here
return bn;
}
The expected algortithm is multiply the vector itself, not with a variable what I convert to this BigNumber.
The way I set Integer to BigNumber:
void BigNumber::setBigNumber(int num)
{
if (num > 0)
{
bigNum.clear();
while (num != 0)
{
bigNum.push_back(num % 10);
num = (num - (num % 10)) / 10;
}
std::reverse(bigNum.begin(), bigNum.end());
}
else
{
throw TOOSMALL;
}
};
The method I want to implement:
//class BigNumber{private: vector<int> bigNum; ... }
void BigNumber::multiplyBigNumber(BigNumber bn, int num)
{
if (num > 0)
{
//bn.bigNum * num
}
else
{
throw TOOSMALL;
}
}
As this is for a school project, I don't want to just write the code for you. So here's a hint.
Let's say you give me the number 1234 --- and I choose to store each digit in a vector in reverse. So now I've got bignum = [4, 3, 2, 1].
Now you ask me to multiply that by 5. So I create a new, empty vector result=[ ]. I look at the first item in bignum. It's a 4.
4 * 5 is 20, or (as you do at school) it is 0 carry 2. So I push the 0 into result, giving result = [0] and carry = 2.
Questions for you:
If you were doing this by hand (on paper), what would you do next?
Why did I decide to store the digits in reverse order?
Why did I decide to use a new vector (result), rather than modifying bignum?
and only after you have a worked out how to multiply a bignum by an int:
How would you multiply two bignums together?
The solutin for the problem is the follow code. I don't know if I can make this algorithm faster, but it works, so I'm happy with it.
BigNumber BigNumber::multiplyBigNumber(BigNumber bn, int num){
if (num > 0)
{
std::vector<int> result;
std::vector<int> rev = bn.getBigNumber();
std::reverse(rev.begin(),rev.end());
int carry = 0;
for(int i = 0; i<rev.size(); i++){
result.push_back((rev[i] * num + carry) % 10);
carry = (rev[i] * num + carry) / 10;
if(i == rev.size()-1 && carry / 10 == 0 && carry % 10 != 0 ) {
result.push_back(carry);
carry = carry / 10;
}
}
while((carry / 10) != 0){
result.push_back(carry % 10);
carry /= 10;
if(carry / 10 == 0) result.push_back(carry);
}
std::reverse(result.begin(),result.end());
bn.setBigNumber(result);
return bn;
}else{
throw TOOSMALL;
}
}

Array value changes unintentionally

At first line, get inputs n (the numbers of nodes), m (the numbers of edges), start (the start node Number) and get the undirected m edges/
In the end, I want to print out the dfs result. However, when I used Node*, it changes. I don't intend to change.
class Node {
private:
int n;
Node* next = 0;
public:
Node(int _n) {
n = _n;
}
Node() {};
Node* getNext() {
return next;
}
void setNext(Node* ptr) {
next = ptr;
}
};
Below code are the main problem.
Node* arr = new Node[n + 1];// use 1 to n
for (int i = 1; i <= m; i++) {
int num1 = 0, num2 = 0;
cin >> num1 >> num2;
if (!arr[num1].getNext())
arr[num1].setNext(&Node(num2));
else {
Node* tptr = arr[num1].getNext();
while (tptr->getNext()) tptr = tptr->getNext();
tptr->setNext(&Node(num2));
}
}
I tried to save the adjacent Nodes(to Node 'i') in the arr[i].
Sample code is:
4 5 1
1 2
1 3
1 4
The result structure I expected was arr[1] -> 2 -> 3 -> 4, but the real outcome was arr[1]-> 2 -> 4 -> 4.
I don't understand why the value changes.

How to find the nth smallest subarray sum bigger than x in a progression where the first two numbers are given?

I have a progression "a", where the first two numbers are given (a1 and a2) and every next number is the smallest sum of subarray which is bigger than the previous number.
For example if i have a1 = 2 and a2 = 3, so the progression will be
2, 3, 5(=2+3), 8(=3+5), 10(=2+3+5), 13(=5+8), 16(=3+5+8),
18(=2+3+5+8=8+10), 23(=5+8+10=10+13), 26(=3+5+8+10), 28(=2+3+5+8+10), 29(=13+16)...
I need to find the Nth number in this progression. ( Time limit is 0.7 seconds)
(a1 is smaller than a2, a2 is smaller than 1000 and N is smaller than 100000)
I tried priority queue, set, map, https://www.geeksforgeeks.org/find-subarray-with-given-sum/ and some other things.
I though that the priority queue would work, but it exceeds the memory limit (256 MB), so i am pretty much hopeless.
Here's what is performing the best at the moment.
int main(){
int a1, a2, n;
cin>>a1>>a2>>n;
priority_queue< int,vector<int>,greater<int> > pq;
pq.push(a1+a2);
int a[n+1];//contains sum of the progression
a[0]=0;
a[1]=a1;
a[2]=a1+a2;
for(int i=3;i<=n;i++){
while(pq.top()<=a[i-1]-a[i-2])
pq.pop();
a[i]=pq.top()+a[i-1];
pq.pop();
for(int j=1; j<i && a[i]-a[j-1]>a[i]-a[i-1] ;j++)
pq.push(a[i]-a[j-1]);
}
cout<<a[n]-a[n-1];
}
I've been trying to solve this for the last 4 days without any success.
Sorry for the bad english, i am only 14 and not from an english speaking coutry.
SOLUTION (Big thanks to n.m. and גלעד ברקן)
V1 (n.m.'s solution)
using namespace std;
struct sliding_window{
int start_pos;
int end_pos;
int sum;
sliding_window(int new_start_pos,int new_end_pos,int new_sum){
start_pos=new_start_pos;
end_pos=new_end_pos;
sum=new_sum;
}
};
class Compare{
public:
bool operator() (sliding_window &lhs, sliding_window &rhs){
return (lhs.sum>rhs.sum);
}
};
int main(){
int a1, a2, n;
//input
cin>>a1>>a2>>n;
int a[n+1];
a[0]=a1;
a[1]=a2;
queue<sliding_window> leftOut;
priority_queue< sliding_window, vector<sliding_window>, Compare> pq;
//add the first two sliding window positions that will expand with time
pq.push(sliding_window(0,0,a1));
pq.push(sliding_window(1,1,a2));
for(int i=2;i<n;i++){
int target=a[i-1]+1;
//expand the sliding window with the smalest sum
while(pq.top().sum<target){
sliding_window temp = pq.top();
pq.pop();
//if the window can't be expanded, it is added to leftOut queue
if(temp.end_pos+1<i){
temp.end_pos++;
temp.sum+=a[temp.end_pos];
pq.push(temp);
}else{
leftOut.push(temp);
}
}
a[i]=pq.top().sum;
//add the removed sliding windows and new sliding window in to the queue
pq.push(sliding_window(i,i,a[i]));
while(leftOut.empty()==false){
pq.push(leftOut.front());
leftOut.pop();
}
}
//print out the result
cout<<a[n-1];
}
V2 (גלעד ברקן's solution)
int find_index(int target, int ps[], int ptrs[], int n){
int cur=ps[ptrs[n]]-ps[0];
while(cur<target){
ptrs[n]++;
cur=ps[ptrs[n]]-ps[0];
}
return ptrs[n];
}
int find_window(int d, int min, int ps[], int ptrs[]){
int cur=ps[ptrs[d]+d-1]-ps[ptrs[d]-1];
while(cur<=min){
ptrs[d]++;
cur=ps[ptrs[d]+d-1]-ps[ptrs[d]-1];
}
return ptrs[d];
}
int main(void){
int a1, a2, n, i;
int args = scanf("%d %d %d",&a1, &a2, &n);
if (args != 3)
printf("Failed to read input.\n");
int a[n];
a[0]=a1;
a[1]=a2;
int ps[n+1];
ps[0]=0;
ps[1]=a[0];
ps[2]=a[0]+a[1];
for (i=3; i<n+1; i++)
ps[i] = 1000000;
int ptrs[n+1];
for(i=0;i<n+1;i++)
ptrs[i]=1;
for(i=2;i<n;i++){
int target=a[i-1]+1;
int max_len=find_index(target,ps, ptrs, n);
int cur=ps[max_len]-ps[0];
int best=cur;
for(int d=max_len-1;d>1;d--){
int l=find_window(d, a[i-1], ps, ptrs);
int cur=ps[l+d-1]-ps[l-1];
if(cur==target){
best=cur;
break;
}
if(cur>a[i-1]&&cur<best)
best=cur;
}
a[i]=best;
ps[i+1]=a[i]+ps[i];
}
printf("%d",a[n-1]);
}
Your priority queue is too big, you can get away with a much smaller one.
Have a priority queue of subarrays represenred e.g. by triples (lowerIndex, upperIndex, sum), keyed by the sum. Given array A of size N, for each index i from 0 to N-2, there is exactly one subarray in the queue with lowerIndex==i. Its sum is the minimal possible sum greater than the last element.
At each step of the algorithm:
Add the sum from the first element of the queue as the new element of A.
Update the first queue element (and all others with the same sum) by extending its upperIndex and updating sum, so it's greater than the new last element.
Add a new subarray of two elements with indices (N-2, N-1) to the queue.
The complexity is a bit hard to analyse because of the duplicate sums in p.2 above, but I guess there shouldn't be too many of those.
It might be enough to try each relevant subarray length to find the next element. If we binary search on each length for the optimal window, we can have an O(n * log(n) * sqrt(n)) solution.
But we can do better by observing that each subarray length has a low bound index that constantly increases as n does. If we keep a pointer to the lowest index for each subarray length and simply iterate upwards each time, we are guaranteed each pointer will increase at most n times. Since there are O(sqrt n) pointers, we have O(n * sqrt n) total iterations.
A rough draft of the pointer idea follows.
UPDATE
For an actual submission, the find_index function was converted to another increasing pointer for speed. (Submission here, username "turnerware"; C code here.)
let n = 100000
let A = new Array(n)
A[0] = 2
A[1] = 3
let ps = new Array(n + 1)
ps[0] = 0
ps[1] = A[0]
ps[2] = A[0] + A[1]
let ptrs = new Array(n + 1).fill(1)
function find_index(target, ps){
let low = 0
let high = ps.length
while (low != high){
let mid = (high + low) >> 1
let cur = ps[mid] - ps[0]
if (cur <= target)
low = mid + 1
else
high = mid
}
return low
}
function find_window(d, min, ps){
let cur = ps[ptrs[d] + d - 1] - ps[ptrs[d] - 1]
while (cur <= min){
ptrs[d]++
cur = ps[ptrs[d] + d - 1] - ps[ptrs[d] - 1]
}
return ptrs[d]
}
let start = +new Date()
for (let i=2; i<n; i++){
let target = A[i-1] + 1
let max_len = find_index(target, ps)
let cur = ps[max_len] - ps[0]
let best = cur
for (let d=max_len - 1; d>1; d--){
let l = find_window(d, A[i-1], ps)
let cur = ps[l + d - 1] - ps[l - 1]
if (cur == target){
best = cur
break
}
if (cur > A[i-1] && cur < best)
best = cur
}
A[i] = best
ps[i + 1] = A[i] + ps[i]
}
console.log(A[n - 1])
console.log(`${ (new Date - start) / 1000 } seconds`)
Just for fun and reference, this prints the sequence and possible indexed intervals corresponding to the element:
let A = [2, 3]
let n = 200
let is = [[-1], [-1]]
let ps = [A[0], A[0] + A[1]]
ps[-1] = 0
for (let i=2; i<n + 1; i++){
let prev = A[i-1]
let best = Infinity
let idxs
for (let j=0; j<i; j++){
for (let k=-1; k<j; k++){
let c = ps[j] - ps[k]
if (c > prev && c < best){
best = c
idxs = [[k+1,j]]
} else if (c == best)
idxs.push([k+1,j])
}
}
A[i] = best
is.push(idxs)
ps[i] = A[i] + ps[i-1]
}
let str = ''
A.map((x, i) => {
str += `${i}, ${x}, ${JSON.stringify(is[i])}\n`
})
console.log(str)
Looks like a sliding window problem to me.
#include <bits/stdc++.h>
using namespace std;
int main(int argc, char** argv) {
if(argc != 4) {
cout<<"Usage: "<<argv[0]<<" a0 a1 n"<<endl;
exit(-1);
}
int a0 = stoi(argv[1]);
int a1 = stoi(argv[2]);
int n = stoi(argv[3]);
int a[n]; // Create an array of length n
a[0] = a0; // Initialize first element
a[1] = a1; // Initialize second element
for(int i=2; i<n; i++) { // Build array up to nth element
int start = i-2; // Pointer to left edge of "window"
int end = i-1; // Pointer to right edge of "window"
int last = a[i-1]; // Last num calculated
int minSum = INT_MAX; // Var to hold min of sum found
int curSum = a[start] + a[end]; // Sum of all numbers in the window
while(start >= 0) { // Left edge is still inside array
// If current sum is greater than the last number calculated
// than it is a possible candidate for being next in sequence
if(curSum > last) {
if(curSum < minSum) {
// Found a smaller valid sum
minSum = curSum;
}
// Slide right edge of the window to the left
// from window to try to get a smaller sum.
// Decrement curSum by the value of removed element
curSum -= a[end];
end--;
}
else {
// Slide left edge of window to the left
start--;
if(!(start < 0)) {
// Increment curSum by the newly enclosed number
curSum += a[start];
}
}
}
// Add the min sum found to the end of the array.
a[i] = minSum;
}
// Print out the nth element of the array
cout<<a[n-1]<<endl;
return 0;
}

How do I do the following recursive function?

Ok, so I have a regular Node list, with members info and next.
I need to use a function, recursively, to calculate the average, and then compare if each node is bigger than the average or not.
int Acount(NodeType* Node, int sum, int& avg){
if (Node == NULL){//last call
avg = sum / avg;
return 0;
}
else {
return (Acount(Node->next, sum + Node->info, ++avg) + (Node->info > avg ? 1 : 0));
}
}
Which is quite simple. Problem is the value returned is always 0.
The problem appears to be with
(Node->info > avg ? 1 : 0));
I've done the tests and when I do the following:
return (Acount(Node->next, sum + Node->info, ++avg) + Node->info;
or
return (Acount(Node->next, sum + Node->info, ++avg) + avg;
Results meet expectations. As in, I'm getting the sum of the Node->info in the first case, and I'm getting average*number of nodes in the second case.
Point of this, I've proved that the function is working perfectly.
Yet when it comes to
(Node->info > avg ? 1 : 0));
Appears to be problematic, which is quite peculiar. if I place for example:
(Node->info == 5 ? 1 : 0));
And there is only one 5 in the nodes, then the function returns 1. So everything is working as intended, yet I keep getting a 0.
The following are the main functions and additional functions for the Node.
#include <iostream>
using std::cout;
using std::cin;
using std::endl;
struct NodeType{
int info;
NodeType *next;
};
//pre: first node passed is not NULL
int Acount(NodeType* Node, int sum, int& avg){
if (Node == NULL){//last call
avg = sum / avg;
return 0;
}
else {
return (Acount(Node->next, sum + Node->info, ++avg) + (Node->info > avg ? 1 : 0));
}
}
void fill(NodeType*& Node){
NodeType *temp;
Node = new NodeType;
Node->info = 0;
Node->next = NULL;
temp = Node;
for (int i = 1; i < 10; i++){
temp->next = new NodeType;
temp = temp->next;
temp->info = i;
temp->next = NULL;
}
}
void print(NodeType* Node){
NodeType *temp = Node;
while (temp != NULL){
cout << temp->info << " ";
temp = temp->next;
}
cout << endl;
}
void Delete(NodeType* Node){
NodeType *temp;
while (Node != NULL){
temp = Node;
Node = Node->next;
delete temp;
}
}
void main(){
int sum = 0, avg = 0;
NodeType *Node;
fill(Node);
print(Node);
cout << Acount(Node, sum, avg) << endl;
Delete(Node);
}
In C++ there is no concept of left-to-right (or right-to-left) evaluation order of expressions. Operator priorities will control associativity, but in the case of f1() + f2() there is no guarantee that f1() is invoked before f2() (and viceversa). It may depend on the compiler or other.
My suggestion is to split the expression into 2 distinct statements as follows:
int tmp = Acount(Node->next, sum + Node->info, ++avg);
return tmp + (Node->info > avg ? 1 : 0);
I am not sure if your code has defined behaviour. But, this line
return (Acount(Node->next, sum + Node->info, ++avg) + (Node->info > avg ? 1 : 0));
depends on if the left summand or the right summand is calculated first.
If it is the left one, then Acount goes down the recursion an incrementing avg until avg equals the number of elements in the list (here 10 when starting from zero called by the main routine). Note, that avg is passed by reference. Thus, when the recursion goes back up, this term in the right summand
Node->info > avg
will never be true because Node->info is set in the fill routine to values smaller then the number of elements.
I don't think your method will work.
In this statement:
return (Acount(Node->next, sum + Node->info, ++avg) + (Node->info > avg ? 1 : 0))
You don't know when the second term has be evaluated. It's not defined in C++.