327 Count of Range Sum
// See the discuss
// See the analysis and using the code from:
// http://www.cnblogs.com/jdneo/p/5388501.html
// It is a solution combining the two pointers & merge sort
// There's the analysis from the page
/*
这道题最直观的一个想法就是枚举出所有的子数组,然后检查他们是否在要求的取值范围内,这种方法的时间复杂度是O(n^2)的,显然会超时。
看到这种题目最容易想到的是什么呢?Two Pointers!对,但是在这道题上仅仅使用Two Pointers肯定是不够的,在Two Pointers的思想基础上,融合归并排序,就能找到一个比较好的解决方案。
这里我们的排序对象是前缀求和数组,在归并排序的合并阶段,我们有左数组和右数组,且左和右数组都是排好序的,所以我们可以用i遍历左数组,j,k两个指针分别取在右数组搜索,使得:
sums[j] - sums[i] < upper
sums[k] - sums[i] >= lower
那么此时,我们就找到了j-k个符合要求的子数组。
The vital sentence: so the values from sums[] are placed in increasing order
由于左右数组都是排好序的,所以当i递增之后,j和k的位置不用从头开始扫描。
最后还有一点需要注意的就是,为了防止溢出,我们的vector容纳的是long long型元素。
*/
// TLE version 1
// using two pointers, and sum[i] represents the sum from
// element 0 to element i
// TLE version 2
// using Segment tree 55/61 passed, the left 6 points are TLE
class Solution {
public:
vector sums;
int lowBound , upBound;
int countRangeSum(vector& nums, int lower, int upper)
{
int lnums = nums.size();
if (lnums == 0) return 0;
lowBound = lower;upBound = upper;
sums.clear();sums.resize(lnums+1);sums[0]=0;
for(int i=0;i= ed) return 0;
int mid = st + (ed - st) / 2;
int result = mergeSum(st,mid) + mergeSum(mid+1,ed);
vector tmp(ed-st+1,0);
int j = mid +1,k =mid +1, t=mid +1, i=st , r=0;
for(;i<=mid;i++,r++)
{
while(j<=ed && sums[j]-sums[i]<=upBound) j++;
while(k<=ed && sums[k]-sums[i]
// Seeing the Discuss & Searching for solution
// Quote the vital sentence:
// """ The smaller numbers on the right of a number are exactly
// those that jump from its right to its left during a stable sort.
// So I do mergesort with added tracking of those right-to-left jumps."""
// smaller[] is to record the result
// the second value of enum/left/right is the original location of the value
// the original locaiton must be recorded
// The code:
/*
def countSmaller(self, nums):
def sort(enum):
half = len(enum) / 2
if half:
left, right = sort(enum[:half]), sort(enum[half:])
m, n = len(left), len(right)
i = j = 0
while i < m or j < n:
if j == n or i < m and left[i][1] <= right[j][1]:
enum[i+j] = left[i]
smaller[left[i][0]] += j
# 想了好久为什么是加上j,也就是加上right当前的下标
# 手动试了下,当选择右边作为小的时候,左边所有剩下没有被选的,
# smaller 都要 +1
# 作者采用的方式就是当选择左边的,
# 说明之前右边被merge过的,都比左边当前的小,所以加上右边剩下的个数
i += 1
else:
enum[i+j] = right[j]
j += 1
return enum
smaller = [0] * len(nums)
sort(list(enumerate(nums)))
return smaller
*/
// Merge sort TLE
// I've tried a version of merge sort
// but there are 2 points I cannot pass.
// Modified the python code from Discuss, 15/16 passed, 1 point TLE
// Do not copy the huge/tremendous vector num during the
// MergeSortPartial/recursion, it will take tremendous time
// then causes TLE
class Solution {
public:
// num vector, pair->first the value, pair->second the original location
vector > num;
vector ans;
int len;
void mergeSort(int left, int right)
{
//cout<<"sort"<= right) return ;
int mid = left +(right - left)/2;
mergeSort(left,mid);
mergeSort(mid+1,right);
mergeSortPartial(left,right);
return ;
}
void mergeSortPartial(int left,int right)
{
//cout<<"partial"<= right) return ;
vector > tmp;tmp.clear();
int mid = left + (right - left)/2;
int i = left, j = mid + 1, index = left;
while(i<=mid && j<=right)
{
if (num[i].first <= num[j].first)
{
ans[num[i].second] += j-1-mid;
tmp.push_back(num[i++]);
}
else
{
tmp.push_back(num[j++]);
}
}
while(i<=mid)
{
ans[num[i].second] += j-1-mid;
tmp.push_back(num[i++]);
}
while(j<=right)
{
tmp.push_back(num[j++]);
}
for(int i=left;i<=right;i++)
{
num[i]=tmp[i-left];
}
return ;
}
void initial(vector nums)
{
len = nums.size();
ans.resize(len);
num.resize(len);
for(int i=0;i countSmaller(vector& nums)
{
initial(nums);
mergeSort(0,len-1);
return ans;
}
};
// Seeing the Discuss & Searching for the Solution
// The analysis from the Discuss
// """
// One knowledge: ab % k = (a%k)(b%k)%k
// Since the power here is an array, we'd better handle it digit by digit.
// One observation:
// a^1234567 % k = (a^1234560 % k) * (a^7 % k) % k
// = (a^123456 % k)^10 % k * (a^7 % k) % k
// Looks complicated? Let me put it other way:
// Suppose f(a, b) calculates a^b % k; Then translate above formula to using f :
// f(a,1234567) = f(a, 1234560) * f(a, 7) % k = f(f(a, 123456),10) * f(a,7)%k;
// """
// the code
/*
class Solution {
const int base = 1337;
int powmod(int a, int k) //a^k mod 1337 where 0 <= k <= 10
{
a %= base;
int result = 1;
for (int i = 0; i < k; ++i)
result = (result * a) % base;
return result;
}
public:
int superPow(int a, vector& b) {
if (b.empty()) return 1;
int last_digit = b.back();
b.pop_back();
return powmod(superPow(a, b), 10) * powmod(a, last_digit) % base;
}
};
*/
// The things learned:
// 1. vector has the function
// .pop_back(): pop the back element
// .back(): get the value of back element
class Solution {
public:
const int base = 1337;
int powmod(int a,int k)
// return the value of a^k mod 1337
// 0<=k<10
{
a %=base;
int result = 1;
for (int i=0;i& b)
{
if (b.empty()) return 1;
int last_digit = b.back();
b.pop_back();
return powmod(superPow(a,b),10) * powmod(a,last_digit) % base;
}
};
class Solution {
public:
vector largestDivisibleSubset(vector& nums)
{
vector ans; ans.clear();
int len = nums.size();
if (len == 0) return ans;
int maxLen = 0;
int maxIndex = 0;
vector f(len,0);
vector route(len);
sort(nums.begin(),nums.end());
for(int i=0;if[i])
{
f[i]=f[j];
route[i]=j;
}
}
}
f[i]++;
if(f[i]>maxLen)
{
maxLen = f[i];
maxIndex = i;
}
}
while(route[maxIndex]!=maxIndex)
{
cout<
/*-------Seeing Discuss & Searching for Solution-------
The discuss is fabulous!
1. Analysis
1.1 Given an array of integers A and an integer k,
find a subarray that contains the largest sum,
subject to a constraint that the sum is less than k?
url:https://www.quora.com/Given-an-array-of-integers-A-and-an-integer-k-find-a-subarray-that-contains-the-largest-sum-subject-to-a-constraint-that-the-sum-is-less-than-k
Solution:
You can do this in O(nlog(n))O(nlog(n))
First thing to note is that sum of subarray (i,j](i,j]
is just the sum of the first jj elements less the sum of the
first ii elements. Store these cumulative sums in the array cum.
Then the problem reduces to finding i,ji,j such that i0 and that
the empty interval with sum zero is a valid answer. The code can be
tweaked easily to take care of more general cases and to return the
interval itself.
Code:
int best_cumulative_sum(int ar[],int N,int K)
{
set cumset;
cumset.insert(0);
int best=0,cum=0;
for(int i=0;i::iterator sit=cumset.upper_bound(cum-K);
if(sit!=cumset.end())best=max(best,cum-*sit);
cumset.insert(cum);
}
return best;
}
1.2 1D -> 2D
first consider the situation matrix is 1D
we can save every sum of 0~i(0<=i::iterator sit=cumset.upper_bound(cum-K);
*/
class Solution {
public:
int maxSumSubmatrix(vector >& matrix, int k)
{
int row = matrix.size();
if (row == 0) return 0;
int ans = INT_MIN;
int col =matrix[0].size();
for(int cStart=0;cStart sums(row,0);
for(int c =cStart;c sumsSet;sumsSet.clear();
// Vital!
// insert the 0 value in case of
// the curSum is equal as the value of k
sumsSet.insert(0);
int curSum = 0 ;
for(int sum:sums)
{
curSum+=sum;
set::iterator it = sumsSet.lower_bound(curSum-k);
if (it!=sumsSet.end())
{
ans = max(ans,curSum - *it);
}
sumsSet.insert(curSum);
}
}
}
return ans;
}
};
// ---------- Seeing the Discuss------------------
/*
1. Analysis
"""Let miss be the smallest sum in [0,n] that we might be missing.
Meaning we already know we can build all sums in [0,miss).
Then if we have a number num <= miss in the given array,
we can add it to those smaller sums to build all sums in [0,miss+num).
If we don't, then we must add such a number to the array, and
it's best to add miss itself, to maximize the reach."""
The thinking is same as me, but I failed in two aspects:
(1) I use the vector to tag the values that can be formed
(2) another solution, I thought, it may only use 1,2,4,8,16,32,.....
but, the correct solution is some thought of this.
2. Code
int minPatches(vector& nums, int n) {
long miss = 1, added = 0, i = 0;
while (miss <= n) {
if (i < nums.size() && nums[i] <= miss) {
miss += nums[i++];
} else {
miss += miss;
added++;
}
}
return added;
}
*/
class Solution {
public:
int minPatches(vector& nums, int n)
{
int len = nums.size();
long long missing = 1, i=0,ans =0;
while(missing <= n)
{
if (i flag; // true for not achieving values
set values;
int cnt, len;
void insertValue(int x,int n)
{
if (x>n || x ==0 || !flag[x]) return ;
flag[x]=false;
cnt++;
values.insert(x);
//cout<<"insert val = "<::iterator it;
for(it=values.begin();it!=values.end();it++)
{
cout<<(*it)<& nums,int n)
{
len = nums.size();
cnt = 0;
values.clear();
//-------------Runtime Error------------
// the size of the vector is too huge
// when n = 2147483647, causing RE
flag.clear(); flag.resize(n+1);
for(int i=0;i<=n;i++) flag[i]=true;
sort(nums.begin(),nums.end());
if (len == 0) return ;
// Using bit manipulation to generate the combinations
// eg: 0001 means there are four items nums[0..3],
// and nums[0] was chosen;
// eg: 1100 means nums[4],nums[3] were chosen.
int biStart = 1, biEnd = (1<>1;
}
insertValue(curSum,n);
}
//printValues();
return ;
}
void insertValueToAll(int val,int n)
{
set tmpSet = values;
for(set::iterator it = tmpSet.begin();it!=tmpSet.end();it++)
{
insertValue((*it)+val,n);
}
insertValue(val,n);
return ;
}
int minPatches(vector& nums, int n)
{
initial(nums,n);
if (cnt == n) return 0;
int last = 1;
int ans = 0;
while(cnt!=n)
{
while(!flag[last]) last++;
insertValueToAll(last,n);
//cout<<"last = "<& nums, int n)
{
set values;
values.clear();
int len = nums.size();
for(int i=0;i
// Using multiset
// Has to using the max value from a set, so using the reverse
// multiset::reverse_iterator it = window.rbegin();
class Solution {
private:
multiset window;
void push(int x)
{
window.insert(x);
return ;
}
void pop(int x)
{
multiset::iterator it = window.find(x);
window.erase(it);
return ;
}
int getMax()
{
multiset::reverse_iterator it = window.rbegin();
return (*it);
}
public:
vector maxSlidingWindow(vector& nums, int k) {
vector ans;
int len=nums.size();
if (len==0) return ans;
window.clear();
for(int i=0;i