While loop exit condition - while-loop

I want to know how this while loop exits? Because i and j are not incremented anywhere except at s.charAt(j++) and s.charAt(i++) which is to find char at j or ith position. Does that also increment j and i? In my opinion it should only give you the character code at j++ or i++ th position isn't it so?
public class Solution {
public int lengthOfLongestSubstring(String s) {
int n = s.length();
Set<Character> set = new HashSet<>();
int ans = 0, i = 0, j = 0;
while (i < n && j < n) {
// try to extend the range [i, j]
if (!set.contains(s.charAt(j))){
set.add(s.charAt(j++));
ans = Math.max(ans, j - i);
}
else {
set.remove(s.charAt(i++));
}
}
return ans;
}
}

Yes using i++ increments the value of i.
If you want to find character at next position than i, then you can simply use another variable and store i+1 value in it and use that to access character. Like this:
z = i+1;
set.add(s.charAt(z));
using post-increment or pre-increment always changes the value of increment variable and only differ as to when they increment the increment variable's value.

Related

Binary search to solve 'Kth Smallest Element in a Sorted Matrix'. How can one ensure the correctness of the algorithm,

I'm referring to the leetcode question: Kth Smallest Element in a Sorted Matrix
There are two well-known solutions to the problem. One using Heap/PriorityQueue and other is using Binary Search. The Binary Search solution goes like this (top post):
public class Solution {
public int kthSmallest(int[][] matrix, int k) {
int lo = matrix[0][0], hi = matrix[matrix.length - 1][matrix[0].length - 1] + 1;//[lo, hi)
while(lo < hi) {
int mid = lo + (hi - lo) / 2;
int count = 0, j = matrix[0].length - 1;
for(int i = 0; i < matrix.length; i++) {
while(j >= 0 && matrix[i][j] > mid) j--;
count += (j + 1);
}
if(count < k) lo = mid + 1;
else hi = mid;
}
return lo;
}
}
While I understand how this works, I have trouble figuring out one issue.
How can we be sure that the returned lo is always in the matrix?
Since the search space is min and max value of the array, the mid need NOT be a value that is in the array. However, the returned lo always is.
Why is this happening?
For the sake of argument, we can move the calculation of count to a separate function like the following:
bool valid(int mid, int[][] matrix, int k) {
int count = 0, m = matrix.length;
for (int i = 0; i < m; i++) {
int j = 0;
while (j < m && matrix[i][j] <= mid) j++;
count += j;
}
return (count < k);
}
This predicate will do exactly same as your specified operation. Here, the loop invariant is that, the range [lo, hi] always contains the kth smallest number of the 2D array.
In other words, lo <= solution <= hi
Now, when the loop terminates, it is evident that lo >= hi
Merging those two properties, we get, lo = solution = hi, since solution is a member of array, it can be said that, lo is always in the array after loop termination and will rightly point to the kth smallest element.
Because We are finding the lower_bound using binary search and there cannot be any number smaller than the number(lo) in the array which could be the kth smallest element.

Looping over an NSmutatable Array starting from a certain index

I have a quick question how can I loop over an NSMutable array starting from a certain index.
For Example I have these double loops I want k to start from the same index as l.
for (Line *l in L)
{
for (Line *k in L)
{
............
}
}
To elaborate further, lets say L has 10 object so l start from 0-10 and k from 0 -10. What I want is if l is equal 1 k should start from 1-10 rather than 0 - 10 and when l is equal 2 k should start from 2- 10 rather than 0. Any help is Appreciated
Objective-C is an extension of C, lookup the C for loop and you'll have your answer. HTH
Addendum
I was going to let you benefit from the learning experience of looking up the C for yourself, however at the time of writing all other answers since added give the code but it is not complete, so here is what you need to produce the l and k values in the order you wish:
for(NSInteger lIndex = 0; lIndex < L.count; lIndex++)
{
Line *l = L[lIndex]; // index into your array to get the element
for(NSInteger kIndex = lIndex; kIndex < L.count; kIndex++)
{
Line *k = L[kIndex];
// process your l and k
}
}
As you can see the for has three sub-parts which are the initialisation, condition, and increment. The initialisation is performed first, then the condition to determine whether to execute the for body, and the increment is executed after the statements in the body and before the condition is tested to determine if another iteration should be performed. A for loop is roughly (there are some differences that are unimportant here) to the while loop:
initialisation;
while(condition)
{
body statements;
increment;
}
You simply need to modify for-statement.
NSInteger indexYouNeed;
NSInteger iterationCount;
for (int i = indexYouNeed; i < iterationCount; i++) {
/* Your code here */
}
You may find this link helpfulll.
You have to use an indexed (ordinary) for loop instead of fast enumeration (for-in):
int l;
for (l=startValue; l<=endValue; l++)
{
int i;
for (int i=l; i<=endValue; i++)
{
ā€¦
}
}

Correct interpretation of pseudocode? JAVA

So i've tried interpreting this pseudocode a friend made and i wasn't exactly sure that my method returns the right result. Anyone who's able to help me out?
I've done some test cases where e.g. an array of [2,0,7] or [0,1,4] or [0, 8, 0] would return true, but not cases like: [1,7,7] or [2,6,0].
Array(list, d)
for j = 0 to dāˆ’1 do
for i = 0 to dāˆ’1 do
for k = 0 to dāˆ’1 do
if list[j] + list[ i] + list[k] = 0 then
return true
end if
end for
end for
end for
return false
And i've made this in java:
public class One{
public static boolean method1(ArrayList<String> A, int a){
for(int i = 0; i < a-1; i++){
for(int j = 0; j < a-1; j++){
for(int k = 0; k < a-1; k++){
if(Integer.parseInt(A.get(i)+A.get(j)+A.get(k)) == 0){
return true;
}
}
}
}
return false;
}
}
Thanks in advance
For a fix to your concrete problem, see my comment. A nicer way to write that code would be to actually use a list of Integer instead of String, because you will then want to convert the strings back to integers. So, your method looks better like this:
public static boolean method(List<Integer> A) {
for (Integer i : A)
for (Integer j : A)
for (Integer k : A)
if (i + j + k == 0)
return true;
return false;
}
See that you don't even need the size as parameter, since any List in Java embeds its own size.
Somehow offtopic
You're probably trying to solve the following problem: "Find if a list of integers contains 3 different ones that sum up to 0". The solution to this problem doesn't have to be O(n^3), like yours, it can be solved in O(n^2). See this post.
Ok, so here is what I believe the pseudo code is trying to do. It returns true if there is a zero in your list or if there are three numbers that add up to zero in your list. So it should return true for following test cases. (0,1,2,3,4,5), (1,2,3,4,-3). It will return false for (1,2,3,4,5). I just used d=5 as a random example. Your code is good for the most part - you just need to add the ith, jth and kth elements in the list to check if their sum equals zero for the true condition.

When can an algorithm have square root(n) time complexity?

Can someone give me example of an algorithm that has square root(n) time complexity. What does square root time complexity even mean?
Square root time complexity means that the algorithm requires O(N^(1/2)) evaluations where the size of input is N.
As an example for an algorithm which takes O(sqrt(n)) time, Grover's algorithm is one which takes that much time. Grover's algorithm is a quantum algorithm for searching an unsorted database of n entries in O(sqrt(n)) time.
Let us take an example to understand how can we arrive at O(sqrt(N)) runtime complexity, given a problem. This is going to be elaborate, but is interesting to understand. (The following example, in the context for answering this question, is taken from Coding Contest Byte: The Square Root Trick , very interesting problem and interesting trick to arrive at O(sqrt(n)) complexity)
Given A, containing an n elements array, implement a data structure for point updates and range sum queries.
update(i, x)-> A[i] := x (Point Updates Query)
query(lo, hi)-> returns A[lo] + A[lo+1] + .. + A[hi]. (Range Sum Query)
The naive solution uses an array. It takes O(1) time for an update (array-index access) and O(hi - lo) = O(n) for the range sum (iterating from start index to end index and adding up).
A more efficient solution splits the array into length k slices and stores the slice sums in an array S.
The update takes constant time, because we have to update the value for A and the value for the corresponding S. In update(6, 5) we have to change A[6] to 5 which results in changing the value of S1 to keep S up to date.
The range-sum query is interesting. The elements of the first and last slice (partially contained in the queried range) have to be traversed one by one, but for slices completely contained in our range we can use the values in S directly and get a performance boost.
In query(2, 14) we get,
query(2, 14) = A[2] + A[3]+ (A[4] + A[5] + A[6] + A[7]) + (A[8] + A[9] + A[10] + A[11]) + A[12] + A[13] + A[14] ;
query(2, 14) = A[2] + A[3] + S[1] + S[2] + A[12] + A[13] + A[14] ;
query(2, 14) = 0 + 7 + 11 + 9 + 5 + 2 + 0;
query(2, 14) = 34;
The code for update and query is:
def update(S, A, i, k, x):
S[i/k] = S[i/k] - A[i] + x
A[i] = x
def query(S, A, lo, hi, k):
s = 0
i = lo
//Section 1 (Getting sum from Array A itself, starting part)
while (i + 1) % k != 0 and i <= hi:
s += A[i]
i += 1
//Section 2 (Getting sum from Slices directly, intermediary part)
while i + k <= hi:
s += S[i/k]
i += k
//Section 3 (Getting sum from Array A itself, ending part)
while i <= hi:
s += A[i]
i += 1
return s
Let us now determine the complexity.
Each query takes on average
Section 1 takes k/2 time on average. (you might iterate atmost k/2)
Section 2 takes n/k time on average, basically number of slices
Section 3 takes k/2 time on average. (you might iterate atmost k/2)
So, totally, we get k/2 + n/k + k/2 = k + n/k time.
And, this is minimized for k = sqrt(n). sqrt(n) + n/sqrt(n) = 2*sqrt(n)
So we get a O(sqrt(n)) time complexity query.
Prime numbers
As mentioned in some other answers, some basic things related to prime numbers take O(sqrt(n)) time:
Find number of divisors
Find sum of divisors
Find Euler's totient
Below I mention two advanced algorithms which also bear sqrt(n) term in their complexity.
MO's Algorithm
try this problem: Powerful array
My solution:
#include <bits/stdc++.h>
using namespace std;
const int N = 1E6 + 10, k = 500;
struct node {
int l, r, id;
bool operator<(const node &a) {
if(l / k == a.l / k) return r < a.r;
else return l < a.l;
}
} q[N];
long long a[N], cnt[N], ans[N], cur_count;
void add(int pos) {
cur_count += a[pos] * cnt[a[pos]];
++cnt[a[pos]];
cur_count += a[pos] * cnt[a[pos]];
}
void rm(int pos) {
cur_count -= a[pos] * cnt[a[pos]];
--cnt[a[pos]];
cur_count -= a[pos] * cnt[a[pos]];
}
int main() {
int n, t;
cin >> n >> t;
for(int i = 1; i <= n; i++) {
cin >> a[i];
}
for(int i = 0; i < t; i++) {
cin >> q[i].l >> q[i].r;
q[i].id = i;
}
sort(q, q + t);
memset(cnt, 0, sizeof(cnt));
memset(ans, 0, sizeof(ans));
int curl(0), curr(0), l, r;
for(int i = 0; i < t; i++) {
l = q[i].l;
r = q[i].r;
/* This part takes O(n * sqrt(n)) time */
while(curl < l)
rm(curl++);
while(curl > l)
add(--curl);
while(curr > r)
rm(curr--);
while(curr < r)
add(++curr);
ans[q[i].id] = cur_count;
}
for(int i = 0; i < t; i++) {
cout << ans[i] << '\n';
}
return 0;
}
Query Buffering
try this problem: Queries on a Tree
My solution:
#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 10, k = 333;
vector<int> t[N], ht;
int tm_, h[N], st[N], nd[N];
inline int hei(int v, int p) {
for(int ch: t[v]) {
if(ch != p) {
h[ch] = h[v] + 1;
hei(ch, v);
}
}
}
inline void tour(int v, int p) {
st[v] = tm_++;
ht.push_back(h[v]);
for(int ch: t[v]) {
if(ch != p) {
tour(ch, v);
}
}
ht.push_back(h[v]);
nd[v] = tm_++;
}
int n, tc[N];
vector<int> loc[N];
long long balance[N];
vector<pair<long long,long long>> buf;
inline long long cbal(int v, int p) {
long long ans = balance[h[v]];
for(int ch: t[v]) {
if(ch != p) {
ans += cbal(ch, v);
}
}
tc[v] += ans;
return ans;
}
inline void bal() {
memset(balance, 0, sizeof(balance));
for(auto arg: buf) {
balance[arg.first] += arg.second;
}
buf.clear();
cbal(1,1);
}
int main() {
int q;
cin >> n >> q;
for(int i = 1; i < n; i++) {
int x, y; cin >> x >> y;
t[x].push_back(y); t[y].push_back(x);
}
hei(1,1);
tour(1,1);
for(int i = 0; i < ht.size(); i++) {
loc[ht[i]].push_back(i);
}
vector<int>::iterator lo, hi;
int x, y, type;
for(int i = 0; i < q; i++) {
cin >> type;
if(type == 1) {
cin >> x >> y;
buf.push_back(make_pair(x,y));
}
else if(type == 2) {
cin >> x;
long long ans(0);
for(auto arg: buf) {
hi = upper_bound(loc[arg.first].begin(), loc[arg.first].end(), nd[x]);
lo = lower_bound(loc[arg.first].begin(), loc[arg.first].end(), st[x]);
ans += arg.second * (hi - lo);
}
cout << tc[x] + ans/2 << '\n';
}
else assert(0);
if(i % k == 0) bal();
}
}
There are many cases.
These are the few problems which can be solved in root(n) complexity [better may be possible also].
Find if a number is prime or not.
Grover's Algorithm: allows search (in quantum context) on unsorted input in time proportional to the square root of the size of the input.link
Factorization of the number.
There are many problems that you will face which will demand use of sqrt(n) complexity algorithm.
As an answer to second part:
sqrt(n) complexity means if the input size to your algorithm is n then there approximately sqrt(n) basic operations ( like **comparison** in case of sorting). Then we can say that the algorithm has sqrt(n) time complexity.
Let's analyze the 3rd problem and it will be clear.
let's n= positive integer. Now there exists 2 positive integer x and y such that
x*y=n;
Now we know that whatever be the value of x and y one of them will be less than sqrt(n). As if both are greater than sqrt(n)
x>sqrt(n) y>sqrt(n) then x*y>sqrt(n)*sqrt(n) => n>n--->contradiction.
So if we check 2 to sqrt(n) then we will have all the factors considered ( 1 and n are trivial factors).
Code snippet:
int n;
cin>>n;
print 1,n;
for(int i=2;i<=sqrt(n);i++) // or for(int i=2;i*i<=n;i++)
if((n%i)==0)
cout<<i<<" ";
Note: You might think that not considering the duplicate we can also achieve the above behaviour by looping from 1 to n. Yes that's possible but who wants to run a program which can run in O(sqrt(n)) in O(n).. We always look for the best one.
Go through the book of Cormen Introduction to Algorithms.
I will also request you to read following stackoverflow question and answers they will clear all the doubts for sure :)
Are there any O(1/n) algorithms?
Plain english explanation Big-O
Which one is better?
How do you calculte big-O complexity?
This link provides a very basic beginner understanding of O() i.e., O(sqrt n) time complexity. It is the last example in the video, but I would suggest that you watch the whole video.
https://www.youtube.com/watch?v=9TlHvipP5yA&list=PLDN4rrl48XKpZkf03iYFl-O29szjTrs_O&index=6
The simplest example of an O() i.e., O(sqrt n) time complexity algorithm in the video is:
p = 0;
for(i = 1; p <= n; i++) {
p = p + i;
}
Mr. Abdul Bari is reknowned for his simple explanations of data structures and algorithms.
Primality test
Solution in JavaScript
const isPrime = n => {
for(let i = 2; i <= Math.sqrt(n); i++) {
if(n % i === 0) return false;
}
return true;
};
Complexity
O(N^1/2) Because, for a given value of n, you only need to find if its divisible by numbers from 2 to its root.
JS Primality Test
O(sqrt(n))
A slightly more performant version, thanks to Samme Bae, for enlightening me with this. šŸ˜‰
function isPrime(n) {
if (n <= 1)
return false;
if (n <= 3)
return true;
// Skip 4, 6, 8, 9, and 10
if (n % 2 === 0 || n % 3 === 0)
return false;
for (let i = 5; i * i <= n; i += 6) {
if (n % i === 0 || n % (i + 2) === 0)
return false;
}
return true;
}
isPrime(677);

My program doesn't get into my second for loop

While doing some work for my lab in university
I am creating this function where there is a for loop inside another one.
It is not important to know what the method is used for. I just can't figure out why the program doesn't enter the second for loop. This is the code:
public void worseFit(int[] array){
int tempPosition = -1;
int tempWeight = 101 ;
for (int x = 0; x < (array.length - 1); x++){
if (allCrates.getSize() < 1){
Crate crate = new Crate();
crate.addWeight(array[0]);
allCrates.add(crate);
} else{
for( int i = 1; i < (allCrates.getSize() - 1); i++ ){
Crate element = allCrates.getElement(i);
int weight = element.getTotalWeight();
if (weight < tempWeight){
tempWeight = weight;
tempPosition = i;
Crate crate = new Crate();
if (weight + tempWeight <= 100){
crate.addWeight(weight + tempWeight);
allCrates.setElement(i, crate);
} else {
crate.addWeight(weight);
allCrates.setElement(allCrates.getSize(), crate);
} // if
} // if
} // for
} // if
} // for
} // worseFit
Once the program enters the else part of the code it goes straight
away back to the beginning of the first for loop.
Would anyone know how to solve this problem?
There seems to be some discrepancies with the expected values of allCrates.getSize().
If allCrates.getSize() returns 2, it will go to the second for loop, but not run it, as i < allCrates.getSize() - 1 will result in false
You might want to use <= instead of <
Initialize the variable i in your second loop to 0 instead of 1. Because if your getSize() returns 1 the it will not enter the if part and after entering the else part the for loop condition will evaluate to false and hence your for loop will not be executed.