Minimum Possible Integer After at Most K Adjacent Swaps On Digits - c++

Given a string num representing the digits of a very large integer and an integer k.
You are allowed to swap any two adjacent digits of the integer at most k times.
Return the minimum integer you can obtain also as a string.
Example 1:
Input: num = "4321", k = 4
Output: "1342"
Explanation: The steps to obtain the minimum integer from 4321 with 4 adjacent swaps are shown.
Input: num = "36789", k = 1000
Output: "36789"
Explanation: We can keep the number without any swaps.
Example 4:
Constraints:
1 <= num.length <= 30000
num contains digits only and doesn't have leading zeros.
1 <= k <= 10^9
Here, is the code
class Solution {
public:
string minInteger(string num, int k) {
int n=num.length();
string min=num;
if (min.compare(num)>0)
min=num;
if (k<1)
return 0;
for (int i=0;i<n-1;i++){
for (int j=i+1;j<n;j++){
if (num[i]>num[j]){
swap(num[i],num[j]);
minInteger(num,k-1,min);
swap(num[i],num[j]);
}
}
}
return min;
}
};
My output ,
Input: num = "4321", k = 4
Output: "1234"
So,basically its returning a string with ascending order of digits which is not desired .
How am I supposed to correct this ?

Problem statement says you can swap only adjacent digits while you try to swap arbitrary two digits in your code.
Instead of those two loops you should have just one that tries to swap digits at position i and i+1.

I think you should just use one loop to swap adjacent digits. In your code you are swapping any two digits. Maybe something like this:
for(int i = 0; i < n-1; ++i) {
if(num[i+1] < num[i]){
swap(num[i+1], num[i]);
// do your stuff
swap(num[i+1], num[i]);
}
}
I hope it helps.

Related

Can someone please explain this bit manipulation code to me?

I am new to competitive programming. I recently gave the Div 3 contest codeforces. Eventhough I solved the problem C, I really found this code from one of the top programmers really interesting. I have been trying to really understand his code, but it seems like I am too much of a beginner to understand it without someone else explaining it to me.
Here is the code.
void main(){
int S;
cin >> S;
int ans = 1e9;
for (int mask = 0; mask < 1 << 9; mask++) {
int sum = 0;
string num;
for (int i = 0; i < 9; i++)
if (mask >> i & 1) {
sum += i + 1;
num += char('0' + (i + 1));
}
if (sum != S)
continue;
ans = min(ans, stoi(num));
}
cout << ans << '\n';
}
The problem is to find the minimum number whose sum of digits is equal to given number S, such that every digit in the result is unique.
Eq. S = 20,
Ans = 389 (3+8+9 = 20)
Mask is 9-bits long, each bit represents a digit from 1-9. Thus it counts from 0 and stops at 512. Each value in that number corresponds to possible solution. Find every solution that sums to the proper value, and remember the smallest one of them.
For example, if mask is 235, in binary it is
011101011 // bit representation of 235
987654321 // corresponding digit
==> 124678 // number for this example: "digits" with a 1-bit above
// and with lowest digits to the left
There are a few observations:
you want the smallest digits in the most significant places in the result, so a 1 will always come before any larger digit.
there is no need for a zero in the answer; it doesn't affect the sum and only makes the result larger
This loop converts the bits into the corresponding digit, and applies that digit to the sum and to the "num" which is what it'll print for output.
for (int i = 0; i < 9; i++)
if (mask >> i & 1) { // check bit i in the mask
sum += i + 1; // numeric sum
num += char('0' + (i + 1)); // output as a string
}
(mask >> i) ensures the ith bit is now shifted to the first place, and then & 1 removes every bit except the first one. The result is either 0 or 1, and it's the value of the ith bit.
The num could have been accumulated in an int instead of a string (initialized to 0, then for each digit: multiply by 10, then add the digit), which is more efficient, but they didn't.
The way to understand what a snippet of code is doing is to A) understand what it does at a macro-level, which you have done and B) go through each line and understand what it does, then C) work your way backward and forward from what you know, gaining progress a bit at a time. Let me show you what I mean using your example.
Let's start by seeing, broadly (top-down) what the code is doing:
void main(){
// Set up some initial state
int S;
cin >> S;
int ans = 1e9;
// Create a mask, that's neat, we'll look at this later.
for (int mask = 0; mask < 1 << 9; mask++) {
// Loop state
int sum = 0;
string num;
// This loop seems to come up with candidate sums, somehow.
for (int i = 0; i < 9; i++)
if (mask >> i & 1) {
sum += i + 1;
num += char('0' + (i + 1));
}
// Stop if the sum we've found isn't the target
if (sum != S)
continue;
// Keep track of the smallest value we've seen so far
ans = min(ans, stoi(num));
}
// Print out the smallest value
cout << ans << '\n';
}
So, going from what we knew about the function at a macro level, we've found that there are really only two spots that are obscure, the two loops. (If anything outside of those are confusing to you, please clarify.)
So now let's try going bottom-up, line-by-line those loops.
// The number 9 appears often, it's probably meant to represent the digits 1-9
// The syntax 1 << 9 means 1 bitshifted 9 times.
// Each bitshift is a multiplication by 2.
// So this is equal to 1 * (2^9) or 512.
// Mask will be 9 bits long, and each combination of bits will be covered.
for (int mask = 0; mask < 1 << 9; mask++) {
// Here's that number 9 again.
// This time, we're looping from 0 to 8.
for (int i = 0; i < 9; i++) {
// The syntax mask >> i shifts mask down by i bits.
// This is like dividing mask by 2^i.
// The syntax & 1 means get just the lowest bit.
// Together, this returns true if mask's ith bit is 1, false if it's 0.
if (mask >> i & 1) {
// sum is the value of summing the digits together
// So the mask seems to be telling us which digits to use.
sum += i + 1;
// num is the string representation of the number whose sum we're finding.
// '0'+(i+1) is a way to convert numbers 1-9 into characters '1'-'9'.
num += char('0' + (i + 1));
}
}
}
Now we know what the code is doing, but it's hard to figure out. Now we have to meet in the middle - combine our overall understanding of what the code does with the low-level understanding of the specific lines of code.
We know that this code gives up after 9 digits. Why? Because there are only 9 unique non-zero values (1,2,3,4,5,6,7,8,9). The problem said they have to be unique.
Where's zero? Zero doesn't contribute. A number like 209 will always be smaller than its counterpart without the zero, 92 or 29. So we just don't even look at zero.
We also know that this code doesn't care about order. If digit 2 is in the number, it's always before digit 5. In other words, the code doesn't ever look at the number 52, only 25. Why? Because the smallest anagram number (numbers with the same digits in a different order) will always start with the smallest digit, then the second smallest, etc.
So, putting this all together:
void main(){
// Read in the target sum S
int S;
cin >> S;
// Set ans to be a value that's higher than anything possible
// Because the largest number with unique digits is 987654321.
int ans = 1e9;
// Go through each combination of digits, from 1 to 9.
for (int mask = 0; mask < 1 << 9; mask++) {
int sum = 0;
string num;
for (int i = 0; i < 9; i++)
// If this combination includes the digit i+1,
// Then add it to the sum, and append to the string representation.
if (mask >> i & 1) {
sum += i + 1;
num += char('0' + (i + 1));
}
// If this combination does not yield the right sum, try the next combination.
if (sum != S)
continue;
// If this combination does yield the right sum,
// see if it's smaller than our previous smallest.
ans = min(ans, stoi(num));
}
// Print the smallest combination we found.
cout << ans << '\n';
}
I hope this helps!
The for loop is iterating over all 9-digit binary numbers and turning those binary numbers into a string of decimal digits such that if nth binary digit is on then a n+1 digit is appended to the decimal number.
Generating the numbers this way ensures that the digits are unique and that zero never appears.
But as #Welbog mentions in comments this solution to the problem is way more complicated than it needs to be. The following will be an order of magnitude faster, and I think is clearer:
int smallest_number_with_unique_digits_summing_to_s(int s) {
int tens = 1;
int answer = 0;
for (int n = 9; n > 0 && s > 0; --n) {
if (s >= n) {
answer += n * tens;
tens *= 10;
s -= n;
}
}
return answer;
}
Just a quick way to on how code works.
First you need to know sum of which digits equal to S. Since each digit is unique, you can assign a bit to them in a binary number like this:
Bit number Digit
0 1
1 2
2 3
...
8 9
So you can check all numbers that are less than 1 << 9 (numbers with 9 bits corresponding 1 to 9) and check if sum of bits if equal to your sum based on their value. So for example if we assume S=17:
384 -> 1 1000 0000 -> bit 8 = digit 9 and bit 7 = digit 8 -> sum of digits = 8+9=17
Now that you know sum if correct, you can just create number based on digits you found.

finding the number of possible decodings of the given number(dynamic programming)

I am trying to solve a problem where every letter has a respective number such as a-1,b-2....z-26.
Now given a number, in how many ways can the number be decoded is the question. consider an example where 25114 can be decoded as 'BEAN',‘BEAAD’, ‘YAAD’, ‘YAN’, ‘YKD’ and ‘BEKD’. this could be decoded in 6 ways.
I have written code in c++ but I am getting the wrong answer. Please correct my code.
#include<bits/stdc++.h>
using namespace std;
int total = 0;
int arr[100001];
void func(int start,int end,int factor){
if(start==end)
return;
int j =start;
if(factor==2&&j==end-1)//if j is the last element and factor is 2,accessing j+1 element is illegual
return;
if(factor==2){
if((arr[j]*10+arr[j+1])>26)
return;
else{
total++;
func(start+2,end,1);
func(start+2,end,2);
}
}
else{//factor is 1
total++;
func(start+1,end,1);
func(start+1,end,2);
}
}
int main(){
int n;
cin>>n;
for(int i=0;i<n;i++){
int p;
cin>>p;
arr[i]=p;
}
func(0,n,1);
func(0,n,2);
cout<<total<<endl;
return 0;
}
essentially what my code is doing is that it fixes one number from the given array(using one digit or two digits from the the given array) and recurses until all the combinations are covered. for example considering the above case, I first choose '2' as my first digit and decode it as 'B'(factor = 1) and then choose '25' and decode it as 'E'(factor = 2).
**following are the input and output from the following code
input : 25114
expected output : 6
my output : 15
input : 3333333333(10 digits)
expected output : 1
my output : 10
Based on the original program from the question I suggest to count the encodings when you reach the end only (if(start==end)).
As func will always be called twice with factor=1 and factor=2, I can freely choose either condition for counting.
Here is the modified code:
#include<bits/stdc++.h>
using namespace std;
int total = 0;
int arr[100001];
void func(int start,int end,int factor){
if(start==end) {
if(factor == 1) total++; // count once when reaching the end
return;
}
int j =start;
if((factor==2) && (j==end-1))//if j is the last element and factor is 2,accessing j+1 element is illegal
return;
if(factor==2){
if((arr[j]*10+arr[j+1])>26)
return;
else{
//total++;
func(start+2,end,1);
func(start+2,end,2);
}
}
else{//factor is 1
//total++;
func(start+1,end,1);
func(start+1,end,2);
}
return;
}
int main(){
int n;
cin>>n;
for(int i=0;i<n;i++){
int p;
cin>>p;
arr[i]=p;
}
func(0,n,1);
func(0,n,2);
cout<<total<<endl;
return 0;
}
This calculates the expected results from the example input in the question.
$ echo 5 2 5 1 1 4|./program
6
$ echo 10 3 3 3 3 3 3 3 3 3 3|./program
1
There is room for improvement.
Instead of modifying a global variable I would return the number of combinations from func and add the values in the higher level.
I would also handle the distinction between 2-digit and 1-digit numbers in the called func instead of in the caller.
Something like this pseudo code:
int func(int start, int end)
{
if(remaining length is <2) {
// we reached the end, so this is one combination
return 1;
}
if(two-digit number is >26) {
// only a 1-digit number is possible, count remaining combinations
return func(start+1, end);
}
// both a 1-digit or 2-digit number is possible, add the remaining combinations for both cases
return func(start+1) + func(start+2);
}
Your question is tagged as "dynamic-programming", but it is anything but.
Instead, think about the state space and its boundary conditions:
The empty string has zero encodings;
A single digit has a single encoding;
An n-digit string has as many encodings as an (n-1)-digit substring plus as many encodings as an (n-2)-digit substring if the first two digits are <= 26.
Thus, we can walk the string from back to front and store the intermediate results for reuse:
uint64_t solve(std::vector<int>& digits) {
const int n = digits.size();
std::vector<int> encodings(n+1);
encodings[n] = 1;
for (int i = n-1; i >= 0; i--) {
bool two_digits_fit = (i < n - 1) && (digits[i] * 10 + digits[i+1]) <= 26; // What if digits[i] == 0?
encodings[i] = encodings[i+1] + (two_digits_fit ? encodings[i+2] : 0);
}
return encodings[0];
}

Given two string S and T. Determine a substring of S that has minimum difference with T?

I have two string S and T where length of S >= length of T. I have to determine a substring of S which has same length as T and has minimum difference with T. Here difference between two strings of same length means, the number of indexes where they differ. For example: "ABCD" and "ABCE" differ at 3rd index, so their difference is 1.
I know I can use KMP(Knuth Morris Pratt) Pattern Searching algorithm to search T within S. But, what if S doesn't contain T as a substring? So, I have coded a brute force approach to solve this:
int main() {
string S, T;
cin >> S >> T;
int SZ_S = S.size(), SZ_T = T.size(), MinDifference = INT_MAX;
string ans;
for (int i = 0; i + SZ_T <= SZ_S; i++) { // I generate all the substring of S
int CurrentDifference = 0; // and check their difference with T
for (int j = 0; j < SZ_T; j++) { // and store the substring with minimum difference
if (S[i + j] != T[j])
CurrentDifference++;
}
if (CurrentDifference < MinDifference) {
ans = S.substr (i, SZ_T);
MinDifference = CurrentDifference;
}
}
cout << ans << endl;
}
But, my approach only works when S and T has shorter length. But, the problem is S and T can have length as large as 2 * 10^5. How can I approach this?
Let's maximize the number of characters that match. We can solve the problem for each character of the alphabet separately, and then sum up the results for
substrings. To solve the problem for a particular character, give string S and T as sequences 0 and 1 and multiply them using the FFT https://en.wikipedia.org/wiki/Fast_Fourier_transform.
Complexity O(|A| * N log N) where |A| size of the alphabet (for an uppercase letter is 26).

Sum of values at common indexes in all subsets?

In a recent problem where i have to sum all values at common indexes in all possible subsets of size k in array of size n.
For eg: If
array ={1,2,3}
Its subsets (k=2) will be (x [i] , x [j]) where i < j
1 2
1 3
2 3
Sum:4,8
Firstly I have used recursion (same that of generating all subsets)
int sum_index[k]={0};
void sub_set(int array[],int n,int k,int temp[],int q=0,int r=0)
{
if(q==k)
{
for(int i=0;i<k;i++)
sum_index[i]+=temp[i];
}
else
{
for(int i=r;i<n;i++)
{
temp[q]=array[i];
sub_set(value,n,k,temp,q+1,i+1);
}
}
}
Problem is its taking too much time then expected .
Then i modified it to...
void sub_set(int array[],int n,int k,int temp[],int q=0,int r=0)
{
if(q==k)
{
return;
}
else
{
for(int i=r;i<n;i++)
{
temp[q]=array[i];
sum_index[q]+=temp[q]; //or sum_index[q]+=s[i];
sub_set(value,n,k,temp,q+1,i+1);
}
}
}
Still taking too much time!!
Is there any other approach to this problem?? Or any other modification i needed that i am unaware of??
Instead of iterating through the possible sub-sets, think of it a combinatorics problem.
To use your example of k=2 and {1,2,3}, let's just look at the first value of the result. It has two 1's and one 2. The two 1's correspond to the number one element sets that can be made from {2, 3} and the one 2 corresponds to the number of one element sets that can be made from {3}. A similar arrangement exists for the one 2 and two 3's in the second element of the result and looking at the subsets of the elements that appear before the element being considered.
Things get a bit more complicated when k>2 because then you will have to look for the number of combinations of elements before and after the element being considered, but the basic premise still works. Multiply the number of possible subsets before times the number of subsets afterwards and that will tell you how many times each element contributes to the result.
A solution in O(n^2) instead of O(n!):
First a tiny (:)) bit of explanation, then some code:
I´m going to assume here that your array is sorted (if not, use std::sort first). Additionally, I´m going to work with the array values 1,2,3,4... here, if you array consists arbitrary values (like 2 8 17), you´ll have to think of it as the indices (ie. 1=>2, 2=>8 etc.)
Definition: (x choose y) means the binomial coefficient, how it is calculated is in the link too. If you have an array size a and some k for the subset size, (a choose k) is the number of permutations, eg. 3 for your example: (1,2), (1,3) and (2,3).
You want the sum for each column if you write the permutations under each other, this would be easy if you knew for each column how many times each array element occurs, ie. how many 1´s, 2´s and 3´s for the first, and how many for second column (with k=2).
Here a bigger example to explain: (1,2,3,4,5) and all possible k´s (each in one block):
1
2
3
4
5
12
13
14
15
23
24
25
34
35
45
123
124
125
134
135
145
234
235
245
345
... (didn´t write k=4)
12345
Let´s introduce column indices, 0<=c<k, ie. c=0 means the first column, c=1 the second and so on; and the array size s=5.
So, looking eg. at the k=3-block, you´ll notice that the lines beginning with 1 (column c=0) have all permutations of the values (2,3,4,5) for k=2, more generally a value x in column c has all permutations for values x+1 to s after it. The values from from x+1 to s are s-x different values, and after column c there are k-c-1 more columns. So, for a value x, you can calculate ((s-x) choose (k-c-1)).
Additionally, the first column has only the values 1,2,3, the last two numbers are not here because after this column there are two more columns.
If you do this for the first column, it works well. Eg. with value 1 in the first column of k=3 above:
count(x) = ((s-x) choose (k-c-1)) = (4 choose 2) = 6
and indeed there are six 1 there. Calculate this count for every array value, multiply x*count(x), and sum it up for every x, that´s the result for the first column.
The other columns are a tiny bit harder, because there can be multiple "permutation blocks" of the same number. To start with, the step above needs a small adjustment: You need a muliplier array somewhere, one multiplier for each array value, and in the beginning each multiplier is 1. In the calculation x*count(x) above, take x*count(x)*muliplier(x) instead.
In the k=3-example, 1 in the first column can be followed by 2,3,4, 2 can be followed by 3,4, and 3 by 4. So the 3-based permutations of the second column need to be counted twice, and the 4-based even three times; more generally so many times like there are smaller values in the previos colums. Multiply that to the current multiplier.
...
Some code:
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
// factorial (x!)
unsigned long long fact(unsigned char x)
{
unsigned long long res = 1;
while(x)
{
res *= x;
x--;
}
return res;
}
//binomial coefficient (n choose k)
unsigned long long binom(unsigned char n, unsigned char k)
{
if(!n || !k) return 1;
return (fact(n) / fact(k)) / fact(n-k);
}
//just for convenience
template<class T> void printvector(std::vector<T> data)
{
for(auto l : data) cout << l << " ";
cout << endl;
}
std::vector<unsigned long long> calculate(std::vector<int> data, int k)
{
std::vector<unsigned long long> res(k, 0); //result data
std::vector<unsigned long long> multiplier(data.size(), 1);
if(k < 1 || k > 255 || data.size() < 1) return res; //invalid stuff
std::sort(data.begin(), data.end()); //as described
for(int column = 0; column < k; column++) //each column separately
{
//count what to multiply to the multiplier array later
std::vector<unsigned long long> newmultiplier(data.size(), 0);
//for each array element in this column
for(int x = column; x <= (data.size() + column - k); x++)
{
//core calculation
res[column] += data[x] * multiplier[x] * binom(data.size() - x - 1, k - column - 1);
//counting the new multiplier factor
for(int helper = x + 1; helper < data.size(); helper++)
newmultiplier[helper]++;
}
//calculating new multiplier
for(int x = 0; x < data.size(); x++)
{
if(newmultiplier[x])
multiplier[x] *= newmultiplier[x];
}
}
return res;
}
int main() {
printvector(calculate({1,2,3}, 2)); //output 4 8
return 0;
}
std::next_permutation may help:
std::vector<int> sub_set(const std::vector<int>& a, int k)
{
std::vector<int> res(k, 0);
std::vector<bool> p(a.size() - k, false);
p.resize(a.size(), true);
do
{
int index = 0;
for (std::size_t i = 0; i != p.size(); ++i) {
if (p[i]) {
res[index++] += a[i];
}
}
} while (std::next_permutation(p.begin(), p.end()));
return res;
}
Live Demo

splitting a number and storing in int array

Is there a way to split a number and store digits in an int array?
I am looking for a way to remove some digits from a number (for a divisible algorithm proof).
for example, if I have a number 12345, I need to perform this operation:
1234 - 5 = 1229
Is there a way to do this?
Use n % 10 to get the last digit and n / 10 to get the others. For example, 5=12345%10, 1234=12345/10.
Convert integer to array:
int array[6];
int n = 123456;
for (int i = 5; i >= 0; i--) {
array[i] = n % 10;
n /= 10;
}
In general, vectors are preferred in C++, especially in this case since you probably don't know in advance the number of digits.
int n = 123456;
vector<int> v;
for(; n; n/=10)
v.push_back( n%10 );
Then v contains {6,5,4,3,2,1}. You may optionally use std::reverse to reverse it.
I am going to give you an answer in sudo code.
int [] makeArrayFromInt (int input){
arr = new int [floor(log(input)/log(10)) + 1]
int index = 0
while(input>0){
arr[index]=input%10
input=input/10
index++
}
return arr
}
The basic idea is to use mod 10 to get the value in a particular digits place and divide by 10 to get to the next digit. Repeat this process until dividing by 10 gives you zero, as this is when you have reached the end of your number. Floor(log(input)/log(10)) + 1 is a trick to find out how many digits a number possesses.