1、You are given a binary tree in which each node contains an integer value.
Find the number of paths that sum to a given value.
The path does not need to start or end at the root or a leaf, but it must go downwards (traveling only from parent nodes to child nodes).
The tree has no more than 1,000 nodes and the values are in the range -1,000,000 to 1,000,000.
Example:
root = [10,5,-3,3,2,null,11,3,-2,null,1], sum = 8
10
/ \
5 -3
/ \
3 2 11
/ \
3 -2 1
Return 3. The paths that sum to 8 are:
- 5 -> 3
- 5 -> 2 -> 1
- -3 -> 11
解题思路:第一个我们可以使用暴力的dfs多重递归进行暴力求解,即判断结点下面还有没有子节点,有的话继续dfs深度搜索,但是由于递归层数很深,这样递归效率比较低,
第二个思路利用哈希表保存和记忆所有前面的二叉树结点之和,二叉树上面一条路径相当于一个一维数组,来寻找和为sum的连续子数组,这时来判断这条路径数组的前i项和与前j项和的差值是否为sum,如果为sum那么肯定有从这个前i项和到前j项和为sum的时候,每一次分支递归都需要更新当前路径上面的哈希表。
多重递归:
Python代码:
Definition for a binary tree node.
class TreeNode:
def init(self, x):
self.val = x
self.left = None
self.right = None
class Solution:
def pathSum(self, root: TreeNode, sum: int) -> int:
if not root:
return 0
return self.dfs(root,sum) + self.pathSum(root.left,sum) + self.pathSum(root.right,sum)#每次递归下一节点,寻找路径和为sum的
def dfs(self,root,path):
if not root:
return 0
path-=root.val
return (1 if path == 0 else 0) + self.dfs(root.left,path) + self.dfs(root.right,path)#如果path不为零的话继续往下面寻找
哈希表记忆和递归:
Python代码:
Definition for a binary tree node.
class TreeNode:
def init(self, x):
self.val = x
self.left = None
self.right = None
class Solution:
def pathSum(self, root: TreeNode, sum: int) -> int:
prefixSumTree = {0:1}
self.count = 0
prefixSum = 0
self.dfs(root, sum, prefixSum, prefixSumTree)
return self.count
def dfs(self, root, sum, prefixSum, prefixSumTree):
if not root:
return 0
prefixSum += root.val
oldSum = prefixSum - sum
if oldSum in prefixSumTree:#去检查曾经是不是有这个前i项和出现过,如果出现过那么肯定有从这个前i项到前j项距离为sum的时候,而且结点元素可能会有正有负,所以保存次数,可能还会不止一次两次
self.count += prefixSumTree[oldSum]
if prefixSum not in prefixSumTree:#将这个前n项和存入哈希表中
prefixSumTree[prefixSum] = 1
else:
prefixSumTree[prefixSum] += 1
self.dfs(root.left, sum, prefixSum, prefixSumTree)#将当前的哈希表传入到下面的递归函数中,保存了当前这条路径的前面的第i项和
self.dfs(root.right, sum, prefixSum, prefixSumTree)
prefixSumTree[prefixSum] -= 1#回到上一层父节点,自然本结点的值不能被包在prefixsum中
2、Given a string s that consists of only uppercase English letters, you can perform at most k operations on that string.
In one operation, you can choose any character of the string and change it to any other uppercase English character.
Find the length of the longest sub-string containing all repeating letters you can get after performing the above operations.
Note:
Both the string’s length and k will not exceed 104.
Example 1:
Input:
s = “ABAB”, k = 2
Output:
4
Explanation:
Replace the two 'A’s with two 'B’s or vice versa.
Example 2:
Input:
s = “AABABBA”, k = 1
Output:
4
Explanation:
Replace the one ‘A’ in the middle with ‘B’ and form “AABBBBA”.
The substring “BBBB” has the longest repeating letters, which is 4.
解题思路:使用头尾双指针和滑窗法,首先模拟出一个代表窗口内各个字符频度的26位的数组,循环遍历字符数组,每次循环都要在滑窗内找出频度最高的一个字符,看可不可以用k个字符直接替换掉其余的字符,如果可以得话,然后再保存这个滑窗的长度进入下一次循环,如果不可以直接替换的话,那么左指针加一,同时频度数组中的对应左指针的字符频度减去1,然后每次循环都用这次的窗口长度比较上一次的窗口长度,这样循环遍历字符串数组数组,最后得出的最大的滑窗长度就是这个替换后的最大的重复字符的长度。
纯c代码:
#define max(a,b) ((a)>(b)?(a):(b))
int maxmix(int* nums) {
int num = 0,maxn = 0,i;
for (i = 0;i<26;i++) {
num += nums[i];//统计频度总数
maxn = max(nums[i],maxn);//找出最大的字符频度
}
return (num-maxn);//返回的是滑窗内的不重复字符的数量
}
int characterReplacement(char * s, int k){
if (!s) {
return 0;//防止空字符串情况
}
int alp[26] = {0};//初始化频度表全部为0
int left = 0,right = 0;//初始化双指针
int last = 0;//最后输出
int len = strlen(s);
for (right = 0;right<len;right++) {//先使用右指针循环,扩大滑窗大小
alp[s[right]-‘A’]++;//频度表加1
while (maxmix(alp)>k) {//当不重复的元素大于能够替换的最大次数时,停止扩大窗口长度并开始缩小窗口长度直到不重复元素的频度小于等于k值为止
alp[s[left]-‘A’]–;
left++;
}
last = max((right-(left-1)),last);
}
return last;
}