You are given an integer array nums consisting of $
n$ elements, and an integer $ k$. Find a contiguous subarray whose
length is equal to $ k$ that has the maximum average value and return
this value. Any answer with a calculation error less than 10−5 will be accepted.
classSolution { public: using LL = longlong; doublefindMaxAverage(vector<int>& nums, int k){ LL sum = 0; for (int i = 0; i < k; i++) { sum += nums[i]; } LL maxSum = sum; for (int i = 0, j = k; j < nums.size(); i++, j++) { sum = sum - nums[i] + nums[j]; maxSum = max(maxSum, sum); } return (double)maxSum / (double)k; } }
Explanation:
This problem uses the Sliding Window technique. To
reduce the calculation when sliding, first we do not compute the average
each time, we can only calculate the sum of the window and divide it at
last when return. Since the length of the window is fixed, so each step
it move we just need to subtract the left margin value and add the value
next to the right margin then the new sum of the window is get. Slide it
step by step and update the maxSum to find the maximum value of
the array.
You are given an integer array height of length
n. There are n vertical lines drawn such that the
two endpoints of the ith
line are (i, 0) and (i, heighti).
Find two lines that together with the x-axis form a container, such
that the container contains the most water.
Return the maximum amount of the water a container can store.
To solve this problem the two pointers technique is
adopted. The left pointer starting at the index 0 and the
right pointer starts at the end of the vector. Use
maxA to keep track of the maximum area found. Then calculate
the current area of the container and update it to the maxA.
And we need to move the two pointers inwards to find the global maximum
area. The method for moving inwards the pointers is to always move the
smaller one (low one) the seeking a greater value that may increase the
area.
we need to know when conditions can make the left and right boundary
values equal and when not.
To the value of search interval boundaris
1
right = mid;
or
1
right = mid + 1;
we need to know how to redefine the boundary values of left
and right.
Loop Invariant
The loop invariant is a property (or expression) that always be
true within every iteration of the loop. For the binary search
problem, the loop invariant here is the search
interval, aka. the value of boundaries left and
right.
Here we discuss this search interval should be left-closed,
right-open or left-closed, right-closed.
Left-closed Right-closed
Interval
Since this is a closed interval, both the left and right boundary
values of the interval should be valid (i.e., legitimate values). There
for, at that time, the left pointer will point to 0, and
the right pointer will point to nums.size()-1.
1
int left = 0, right = nums.size() - 1;
For the loop condition, since both the left and right boundaris can
be included in a closed interval, it is reasonable for the left and
right boundaries to be equal. Therefore, the condition for the
while loop should be left <= right.
When updating the boundary values in this case, we should notice that
the right boundary is closed, thus the new right boudary is mid − 1 when
nums[mid] > target and left boundary is mid + 1 when
nums[mid] < target.
Left-closed Right-open
Interval
Similar to the left-closed right-closed interval, the boundary values
are updated in the same way. However, in this case, since the right
boundary is open, the condition of the while loop should be
left < right here. And when updating boundary values,
the right one should be $ mid$ rather than mid + 1 because
the boundary value is included by the interval.
classSolution { public: voidmoveZeroes(vector<int>& nums){ int left = 0; for (int right = 0; right < nums.size(); right++) { if (nums[right] != 0) { swap(nums[right], nums[left]); left++; } } } }
Explanation: The solution use two pointers to
separatly point to a non-zero value and a zero value. Initialy, these
two point both point to the index 0. And if the right pointer is not 0,
two pointers will be moved to their next index simultaneously. When the
left point meets a zero value, it will stay on it, and swap the value
with the right pointer. In other words, the zeroes with move to the tail
of the vector like bulbles (imagine the bulble sort algorithm).
Given an array of characters chars, compress it
using following algorithm:
Begin with an empty string s. For each group of
consecutive repeating characters in chars:
If the group length is 1, append
the character to s.
Otherwise, append the charactoer followed by the group’s
length.
The compressed string s should not be returned
separately, but instead, be stored in the input character array
chars. Note that group lengths that are 10 or longer will be split into multiple
characters in chars.
After modifying the input array, return the new length of the
array.
classSolution { public: intcompress(vector<char>& chars){ int ans = 0;
for (int i = 0; i < chars.size();) { constchar letter = chars[i]; int count = 0;
while (i < chars.size() && chars[i] == letter) { count++; i++; }
chars[ans++] = letter;
if (count > 1) { for (constchar c : to_string(count)) { chars[ans++] = c; } } } return ans; } }
Explanation:
Using two pointers to iterate original string and trach generated new
string. Here, use i to iterate whole string and count
the length of each group. Once a group’s length is detected, use another
pointer ans to write on the original string.
Given an integer array nums, return true if
there exists a triple of indices $\[i, j,
k\]$ such that $ i j k$ and numsi < numsj < numsk.
If no such indices exists, return false.
You have a long flowerbed in which some of the plots are planted, and
some are not. However, flowers cannot be planted in
adjacent plots.
Given an integer array flowerbed containing
0s and 1s, where 0 means empty and 1
means not empty, and an integer n, return
true if n new flowers can be planted in the
flowerbed without violating the no-adjacent flowers rule and
false otherwise.
classSolution { public: boolcanPlaceFlowers(vector<int>& flowerbed, int n){ for (int i = 0; i < flowerbed.size(); i++) { bool left = i == 0 || flowerbed[i - 1] == 0; bool right = i == flowerbed.size() - 1 || flowerbed[i + 1] == 0;
if (left && right && flowerbed[i] == 0) { flowerbed[i] = 1; n--; } }
return n <= 0; } };
Explanation:
The basic idea of this solution is very simple: traverse the whole
array, figure out that whether current place is legal for
planting a new flower by looking left and looking right at each plot. If
a plot is 0 and its left and right plots are both 0
either, it would a legal plot to plant, then we plant a new flower here
by marking 1 and, accordingly, the total amount of flowers
should be lessen. Also, here are two exceptional conditons, the boarder
plots. So we need to judge them separatedly by looking right at the left
margin and looking left at the right margin, the logic is same as other
plots.
At last, we just need to simply check that whether all of the flowers
have been planted, if yes return true, otherwise return
false.
Explanation: For two strings, if they are consisted
by the same substrings (or same ingradient), their combination in
opposite order should be the same. For example, is string A is
ababab, string b is abab, it’s
obvious that they have the same ingradient ab, so let’s
combine them as $ a + b $ and $ b + a $, their results should be same.
So, after we make sure that both two strings are made of the same
ingradient, we can use gcd to find their greatest
common division.
Proof: Assume str1 = nX
and str2 = mX
where X represents the common
divisor of these two strings. Thus, the concatenated string str1 + str2
equals (n + m)X. We get
substring of length gcd(len1, len2),
if this length equals the size of str2,
which means the size of str2 is
divisible by str1,
any division should be equal when divised by gcd(str1, str2).
The core is that str1 + str2 = str2 + str1.