Bubble Sorting - confused about 2 lines (Beginner) - bubble-sort

I understood most of the code however I'm just confused about two lines
position = position + 1
N = N - 1
What do they do in the code and why are they at the end? What alternative ways are there to write these two lines? Is there a more efficient way of writing this code?
data = [8,7,12,4,9,6,5]
N = len(data)
swapped = True
while swapped:
swapped = False
position = 0
while (position < N - 1):
if (data[position] > data[position + 1]):
hold = data[position]
data[position] = data[position + 1]
data[position + 1] = hold
else:
swapped = True
position = position + 1
N = N - 1
print(data)

len(data)=7 // length of array
position=0 //to set at beginning of the array
while(position<N-1) // scans your entire array till end of the array
if(data[position]>data[position+1]) // checks if 8 >7 if true store 8 in temp variable
then loop through to get smallest number at data[position] and
else
N=N-1 //get next value of N to meet the condition data[position]>data[position+1]
// prints(sorted array)
Equivalent code in C:
for(int x=0; x<n; x++)
{
for(int y=0; y<n-1; y++)
{
if(array[y]>array[y+1])
{
int temp = array[y+1];
array[y+1] = array[y];
array[y] = temp;
}
}
}
Notice that this will always loop n times from 0 to n, so the order of this algorithm is O(n^2). This is both the best and worst case scenario because the code contains no way of determining if the array is already in order.
Well "I think the bubble sort would be the wrong way to go." :)

Related

Array-Sum Operation

I have written this code using vector. Some case has been passed but others show timeout termination error.
The problem statement is:-
You have an identity permutation of N integers as an array initially. An identity permutation of N integers is [1,2,3,...N-1,N]. In this task, you have to perform M operations on the array and report the sum of the elements of the array after each operation.
The ith operation consists of an integer opi.
If the array contains opi, swap the first and last elements in the array.
Else, remove the last element of the array and push opi to the end of the array.
Input Format
The first line contains two space-separated integers N and M.
Then, M lines follow denoting the operations opi.
Constraints :
2<=N,M <= 10^5
1 <= op <= 5*10^5
Output Format
Print M lines, each containing a single integer denoting the answer to each of the M operations.
Sample Input 0
3 2
4
2
Sample Output 0
7
7
Explanation 0
Initially, the array is [1,2,3].
After the 1st operation, the array becomes[1,2,4] as opi = 4, as 4 is not present in the current array, we remove 3 and push 4 to the end of the array and hence, sum=7 .
After 2nd operation the array becomes [4,2,1] as opi = 2, as 2 is present in the current array, we swap 1 and 4 and hence, sum=7.
Here is my code:
#include <bits/stdc++.h>
using namespace std;
int main()
{
long int N,M,op,i,t=0;
vector<long int > g1;
cin>>N>>M;
if(N>=2 && M>=2) {
g1.reserve(N);
for(i = 1;i<=N;i++) {
g1.push_back(i);
}
while(M--) {
cin>>op;
auto it = find(g1.begin(), g1.end(), op);
if(it != (g1.end())) {
t = g1.front();
g1.front() = g1.back();
g1.back() = t;
cout<<accumulate(g1.begin(), g1.end(), 0);
cout<<endl;
}
else {
g1.back() = op;
cout<<accumulate(g1.begin(), g1.end(), 0);
cout<<endl;
}
}
}
return 0;
}
Please Suggest changes.
Looking carefully in question you will find that the operation are made only on the first and last element. So there is no need to involve a whole vector in it much less calculating the sum. we can calculate the whole sum of the elements except first and last by (n+1)(n-2)/2 and then we can manipulate the first and last element in the question. We can also shorten the search by using (1<op<n or op==first element or op == last element).
p.s. I am not sure it will work completely but it certainly is faster
my guess, let take N = 3, op = [4, 2]
N= [1,2,3]
sum = ((N-2) * (N+1)) / 2, it leave first and last element, give the sum of numbers between them.
we need to play with the first and last elements. it's big o(n).
function performOperations(N, op) {
let out = [];
let first = 1, last = N;
let sum = Math.ceil( ((N-2) * (N+1)) / 2);
for(let i =0;i<op.length;i++){
let not_between = !(op[i] >= 2 && op[i] <= N-1);
if( first!= op[i] && last != op[i] && not_between) {
last = op[i];
}else {
let t = first;
first = last;
last = t;
}
out.push(sum + first +last)
}
return out;
}

Generating random number and avoid duplicated value

I'm now trying to:
1. Generate four number randomly.
2. Store them in array.
3. Make sure the value in array don't duplicate.
Here is my idea:
1. Generate one number each time in for loop (x4 times)
2. After generating number, using inner loop to compare it to the previous array value.
My code:
do
{
for (int i = 0; i < 4; i++)
{
value[i] = rand() % 6 + 1; // Generating value
for (int j = 0; i > j; j++)
{
if (value[i] == value[j])
{
dup = true; break;
}
if (dup == true) break;
}
}
for (int i = 0; i < 4; i++)
{
cout << "value: " << value[i] << " " << endl;
}
} while (dup != true);
I was wondering why same array value will still be generating, as in my code, the loop will be repeating until no more duplicated value is found.
There is a logical flaw in your code. By the time you're breaking from the loop you have already stored the duplicate value generated by rand into your 'value' array. You will have to either re-process the index until you don't get a duplicate -or- use a better data structure.
Why not use a set<int> that way it will only hold unique values and you can exit/break when you've populated N unique elements.
In terms of why you're getting a duplicate result, it's because you're continuing to try again while (dup != true). Read that carefully: while there is not a duplicate, keep trying.
That means it will keep trying until there is a duplicate.
In any case, that sort of problem is generally best solved with a Fisher Yates shuffle but, for this small search space (four from six), you could get away with your scheme.
However, it's probably better done as checking each number against every previous number, along the lines of:
def getFourFromSix():
num = []
num.append (random(1..6))
num.append (num[0])
while num[1] == num[0]:
num[1] = random(1..6)
num.append (num[0])
while num[2] == num[0] or num[2] == num[1]:
num[2] = random(1..6)
num.append (num[0])
while num[3] == num[0] or num[3] == num[1] or num[3] == num[2]:
num[3] = random(1..6)
return num
That way, you're not actually going all the way back and restarting every time you find a duplicate, you only have to try again on the current number.
If you do want a Fisher Yates shuffle (and it's a little more elegant if the pool of numbers gets larger), an M-from-N variant is as simple as:
def getMFromN(m, n):
# Sanity checking.
if m > n:
throw "Trying to extract too many things"
num = []
# Populate choices that we will select from.
for index in 0..n-1:
choice[index] = index + 1
# For each desired number.
for index in 0..m:
# Copy from choices to results.
choose = random(0..n-1)
num.append (choice[choose])
# Remove from results so no repeats.
n = n - 1
choice[choose] = choice[n]
return num

edit distance solution with O(n) space issue

Found a few different solutions and debugging, and especially interested in below solution which requires only O(n) space, other than store a matrix (M*N). But confused about what is the logical meaning of cur[i]. If anyone have any comments, it will be highly appreciated.
I posted solution and code.
Given two words word1 and word2, find the minimum number of steps required to convert word1 to word2. (each operation is counted as 1 step.)
You have the following 3 operations permitted on a word:
a) Insert a character
b) Delete a character
c) Replace a character
class Solution {
public:
int minDistance(string word1, string word2) {
int m = word1.length(), n = word2.length();
vector<int> cur(m + 1, 0);
for (int i = 1; i <= m; i++)
cur[i] = i;
for (int j = 1; j <= n; j++) {
int pre = cur[0];
cur[0] = j;
for (int i = 1; i <= m; i++) {
int temp = cur[i];
if (word1[i - 1] == word2[j - 1])
cur[i] = pre;
else cur[i] = min(pre + 1, min(cur[i] + 1, cur[i - 1] + 1));
pre = temp;
}
}
return cur[m];
}
};
You can think of cur as being as a mix of the previous line and the current line in the edit distance matrix. For example, think of a 3x3 matrix in the original algorithm. I'll number each position like below:
1 2 3
4 5 6
7 8 9
In the loop, if you are computing the position 6, you only need the values from 2, 3 and 5. In that case, cur will be exactly the values from:
4 5 3
See the 3 in the end? That's because we didn't updated it yet, so it still has a value from the first line. From the previous iteration, we have pre = 2, because it was saved before we computed the value at 5.
Then, the new value for the last cell is the minimum of pre = 2, cur[i-1] = 5 and cur[i] = 3, exactly the values mentioned before.
EDIT: completing the analogy, if in the O(n^2) version you compute min(M[i-1][j-1], M[i][j-1], M[i-1][j]), in this O(n) version you'll compute min(pre, cur[i-1], cur[i]), respectively.

How to optimize my Langford Sequence function?

This is my code for making a Langford Sequence out of an array of pairs of numbers (112233 -> 312132). I wanted to write a recursive function, because I wasn't able to find one online anywhere as a self-improvement exercise with algorithms. My question is, how do I optimize it? Is there a way to apply dynamic programming to this and have a better time/space complexity with emphasis on time complexity? My current Runtime complexity is O(n^2) and Space complexity of O(n). Any sort of help in writing cleaner code is also appreciated. Thanks. Also, is this a P or an NP problem?
#include <iostream>
using namespace std;
const int arrLen = 8;
const int seqLen = 8;
bool langfordSequence(int * arr, int indx, int *seq, int pos);
int main() {
int arr[] = {1,1,2,2,3,3,4,4};
int seq[] = {0,0,0,0,0,0,0,0};
bool test = langfordSequence(arr, 0, seq, 0);
if (test)
cout << "Langford Sequence Successful: " << endl;
else
cout << "Langford Sequence Failed: " << endl;
for (int i = 0; i < seqLen; i++)
{
cout << seq[i] << " ";
}
return 0;
}
bool langfordSequence(int * arr, int indx, int *seq, int pos)
{
if (indx >= arrLen - 1) //this means we've reached the end of the array
return true;
if (pos + arr[indx] + 1 >= seqLen) //if the second part of the number is off the array
return false;
if (seq[pos] == 0 && seq[pos + arr[indx] + 1] == 0)
{
seq[pos] = arr[indx];
seq[pos + arr[indx] + 1] = arr[indx];
if (langfordSequence(arr, indx + 2, seq, 0)) //the current pair is good, go to the next one, start from the beginning
return true;
else
{
seq[pos] = 0;
seq[pos + arr[indx] + 1] = 0;
if (langfordSequence(arr, indx, seq, pos + 1))
return true;
}
}
else
{
if (langfordSequence(arr, indx, seq, pos + 1)) //current position is no good, try next position
return true;
}
}
Here’s pseudocode for the idea I was referring to in my comments. I haven’t searched to see who else has done something like this yet (because I like to solve things myself first) but someone else probably has priority.
Algorithm LANGFORD
Parameters N (largest element in the top-level, final sequence), M (largest element of the intermediate, hooked sequence). At the top level, M = N.
Returns: A list of all sequences of length 2N such that each element j in 1..M appears exactly twice separated by exactly j elements and the position of the second M is less than N + M/2 + 1. All other elements of the sequence are set to 0.
If M == 1 (base case)
Let S' := []
For i := 0 to N-2
Let s' be the length 2N sequence containing the subsequence "101" starting at position i (counting from 0), and zero everywhere else.
Insert s' into S'
Return S'
Otherwise: (inductive case)
Let S' := []
Let S := LANGFORD(N,M-1)
For each s in S
Let r := reverse(s)
For i := 0 to floor(N - M/2 + 1)
If s[i] == s[i+M+1] == 0
Let s' be s with s'[i] and s'[i+M+1] replaced by M
Insert s' into S'
If r != s and r[i] == r[i+M+1] == 0
Let r' be r with r'[i] and r'[i+M+1] replaced by M
Insert r' into S'
Return S'
Running this algorithm for N = 4, we have initially M = 4 and recurse until N = 4, M = 1. This step gives us the list [[10100000],[01010000],[00101000]]. We pass this back up to the M=2 step, which finds the hooked sequences [[12102000],[10120020],[20020101],[02002101],[00201210],[01210200],[20021010],[00201210],[20121000],[02012100]]. Passing these up to the M=3 step, we get [[30023121],[13120320],[13102302],[31213200],[23021310],[23121300],[03121320]]. Finally, we return to the top-level function and find the sequence [[41312432]], which also represents its symmetric dual 23421314.
Essentially, we're trying to fit each puzzle piece like "30003" into each potential solution, keeping in mind that the mirror image of any solution is a solution. The time and space complexity are dominated by the combinatorial explosion of potential solutions for values of M around N/2. It might be fast to store the sequences as byte arrays aligned to use vector instructions, and the lists as array lists (vector in C++, [sequence] in Haskell, etc.).

Converting MatLab code - Confused

Basically, I have this final piece of code to convert from MatLab to C++.
The function takes in a 2D vector and then checks the elements of the 2D vector against 2 criteria and if not matched, it removes the blocks. But I'm confused to what the code in MatLab wants to be returned, a 2D or a 1D vector? Here is the code:
function f = strip(blocks, sumthresh, zerocrossthresh)
% This function removes leading and trailing blocks that do
% not contain sufficient energy or frequency to warrent consideration.
% Total energy is measured by summing the entire vector.
% Frequency is measured by counting the number of times 0 is crossed.
% The parameters sumthresh and zerocrossthrech are the thresholds,
% averaged across each sample, above which consideration is warrented.
% A good sumthresh would be 0.035
% A good zerocrossthresh would be 0.060
len = length(blocks);
n = sum(size(blocks)) - len;
min = n+1;
max = 0;
sumthreshtotal = len * sumthresh;
zerocrossthreshtotal = len * zerocrossthresh;
for i = 1:n
currsum = sum(abs(blocks(i,1:len)));
currzerocross = zerocross(blocks(i,1:len));
if or((currsum > sumthreshtotal),(currzerocross > zerocrossthreshtotal))
if i < min
min = i;
end
if i > max;
max = i;
end
end
end
% Uncomment these lines to see the min and max selected
% max
% min
if max > min
f = blocks(min:max,1:len);
else
f = zeros(0,0);
end
Alternatively, instead of returning another vector (whether it be 1D or 2D) might it be better to actually send the memory location of the vector and remove the blocks from it? So for example..
for(unsigned i=0; (i < theBlocks.size()); i++)
{
for(unsigned j=0; (j < theBlocks[i].size()); j++)
{
// handle theBlocks[i][kj] ....
}
}
Also, I do not understand this line:
currsum = sum(abs(blocks(i,1:len)));
Basically the: (i,1:len)
Any ideas? Thanks :)
blocks(i,1:len) is telling the array that it wants to go from blocks[i][1 to the end]. So if it was a 3x3 array it's doing something like:
blocks[i][1]
blocks[i][2]
blocks[i][3]
.
.
.
blocks[i][end]
Then it's taking the absolute value of the contents of the matrix and adding them together. It's returning a [x][x] matrix but the length is either going to be a 0x0 or of (max)X(len).