三个循环暴力
C++
class Solution {
public:
int unequalTriplets(vector<int>& nums) {
int n=nums.size(),ans=0;
for(int i=0;i<n;i++){
for(int j=i+1;j<n;j++){
for(int k=j+1;k<n;k++){
if(nums[i]!=nums[j]&&nums[i]!=nums[k]&&nums[j]!=nums[k]) ans++;
}
}
}
return ans;
}
};
Python:
class Solution:
def unequalTriplets(self, nums: List[int]) -> int:
n=len(nums)
ans=0
for i in range(n):
for j in range(i+1,n):
for k in range(j+1,n):
if nums[i]!=nums[j] and nums[i]!=nums[k] and nums[j]!=nums[k]:
ans+=1
return ans
这里肯定是要用到二叉树的性质来写的,但是我直接没有思考当成二叉树来做,把所有节点拿到,然后用二分查。
C++:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
vector<int> vec;
void dfs(TreeNode* root){
if(root==nullptr) return;
dfs(root->left);
vec.push_back(root->val);
dfs(root->right);
}
vector<vector<int>> closestNodes(TreeNode* root, vector<int>& q) {
dfs(root);
sort(vec.begin(),vec.end());
int n=vec.size();
vector<vector<int> >res;
for(auto &x:q){
int pos=lower_bound(vec.begin(),vec.end(),x)-vec.begin();
if(pos>=0&&pos<n&&vec[pos]==x){
res.push_back({x,x});
}
else{
int mi=-1,mx=-1;
if(pos>=1) mi=vec[pos-1];
if(pos>=n) mx=-1;
else mx=vec[pos];
res.push_back({mi,mx});
}
}
return res;
}
};
Python:
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def closestNodes(self, root: Optional[TreeNode], queries: List[int]) -> List[List[int]]:
arr=[]
def dfs(root:Optional[TreeNode]):
if root is None:
return
dfs(root.left)
arr.append(root.val)
dfs(root.right)
dfs(root)
ans=[]
for x in queries:
pos=bisect_right(arr,x)
min=arr[pos-1] if pos else -1
pos= bisect_left(arr, x)
max=arr[pos] if pos<len(arr) else -1
ans.append([min,max])
return ans
思维+树遍历
中午的时候实在没想明白,没有转化题目的意思
把整个地图看成0为根节点的树,显然从树的叶子节点往上接人,这样油耗更低。无论车子座位有没有限制这都是成立的。
那么如果当前节点为u
,它的子树有
S
u
S_{u}
Su个节点,那么这个这些人至少需要
S
u
+
s
e
a
t
s
−
1
s
e
a
t
s
\frac{S{u}+seats-1}{seats}
seatsSu+seats−1辆车才能送往0出。
class Solution:
def minimumFuelCost(self, roads: List[List[int]], seats: int) -> int:
ans=0
g = [[] for _ in range(len(roads)+1)]
for x,y in roads:
g[x].append(y)
g[y].append(x)
def dfs(u:int,fa:int) -> int:
ret=1
for v in g[u]:
if v==fa: continue
t=dfs(v,u)
ret+=t
nonlocal ans;
ans+=(seats-1+t)//seats
return ret
dfs(0,-1)
return ans
思路:递推DP
DP表示:
dp[i][j]表示前i个字符,分成j段的方案数。
DP转移方程就有:
dp[i][j]=sum(dp[1][j-1]~dp[i-minlength][j-1]) // 前提是合法,如果第i个字符不能满足分割,那么这个也不用枚举了
如果直接枚举的话时间复杂度 O ( n 2 k ) O(n^2k) O(n2k) 1000显然会超时。
可以发现每次要求都从j-1段的,1~i-minlength的和,可以对f[i][j]
做前缀和。
class Solution {
public:
bool chk(char s){
return s=='2'||s=='3'||s=='5'||s=='7';
}
int beautifulPartitions(string s, int k, int minLensumth) {
if(!chk(s[0])) return 0;
int n=s.size();
const int mod=1e9+7;
long long f[n+1][k+1],sum[n+1][k+1];
memset(f,0,sizeof(f));
memset(sum,0,sizeof(sum));
f[0][0]=1;//如果空串分割0次答案为1
sum[0][0]=1;
for(int i=1;i<=n;i++){
if(i>=minLensumth && !chk(s[i-1]) && (i==n|| chk(s[i])))//分割之后的下一个字符为质数,才可以分割
for(int j=1;j<=k;j++){// 从i-minlensumth开始求和到i,j-1段的
f[i][j]=sum[i-minLensumth][j-1];
}
for(int j=0;j<=k;j++){
sum[i][j]=(sum[i-1][j]+f[i][j])%mod;
}
}
return f[n][k];
}
};