【LeetCode】113. Path Sum II 基于Java和C++的解法及分析

113. Path Sum II

 Total Accepted: 80509 Total Submissions: 284188 Difficulty: Medium

Given a binary tree and a sum, find all root-to-leaf paths where each path's sum equals the given sum.

For example:
Given the below binary tree and  sum = 22 ,
              5
             / \
            4   8
           /   / \
          11  13  4
         /  \    / \
        7    2  5   1

return

[
   [5,4,11,2],
   [5,8,4,5]
]

【分析】
      此题和【LeetCode】112题基本方法一样,但要复杂一些。由于合法路径要求为根节点到叶子节点(root to leaf),搜索算法我们采用DFS(深度优先搜索),搜索路径采用中序遍历(左-根-右),由于满足要求的路径可能非唯一,搜索中需要注意“回溯”。
     结合题目中的例子,简述思路如下:
     1.采用中序遍历,则从根节点5起,首先搜索左孩子节点,一直到达叶子节点为止,第一条合法路径为:5-4-11-7, 检验路径和是否满足约束条件(sum==22);
     2.若满足则将路径保存起来;
     3.然后,当前路径尾端数据弹出,剩余5-4-11,返回,相当于回到根节点11;
     4.继续搜索右孩子结点,2为叶子节点,因而合法路径为:5-4-11-2,检验其是否满足约束条件;
     5.....

    【注意事项】 执行当前路径尾端数据弹出的操作有两个位置:
     1.遍历至叶子节点,形成合法路径,在检验路径是否满足约束条件并保存后,弹出末端数据,返回,如此便可回到最近的根节点,然后继续搜索该根节点的子节点;
     2.某一根节点的左右子节点遍历完毕,如根节点11的子节点7和2遍历完毕,须返回上一层,这时候需要弹出根节点11,则当前搜索路径变为:5-4;根节点4没有右叶子节点,弹出4,返回上一层5,根节点5有右子节点,继续中序遍历...

【基于C++的解法】
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    vector<vector<int>> pathSum(TreeNode* root, int sum) {
        
        vector<vector<int>> result;//存放满足要求的路径
        vector<int> cur;//当前路径
        if(root==NULL)return result;
        
        DFS(result,cur,root,sum);//深度搜索
        return result;
    }
    
    void DFS(vector<vector<int>> &result,vector<int> &cur,TreeNode* root,int sum)
    {
        if(root==NULL)return;
        if(root->left==NULL&&root->right==NULL)//到达叶子节点,形成合法路径,这时候再对路径进行验证
        {
            cur.push_back(root->val);//叶子节点纳入当前路径
            if(sumOfPath(cur)==sum)//检验路径是否满足约束
            result.push_back(cur);
            
            cur.pop_back();//弹出当前路径末端数据并返回
            return;
        }
        else
        {
            cur.push_back(root->val);//中序遍历的构架
            DFS(result,cur,root->left,sum);
            DFS(result,cur,root->right,sum);
            cur.pop_back();//某一根节点的子节点搜索完毕,末端数据弹出,返回上一层
        }
    
    }
    
    int sumOfPath(vector<int> &dataSet)//求取路径和
    {
        int sum=0;
        for(int i=0;i<dataSet.size();i++)
        {
            sum+=dataSet[i];
        }
        return sum;
    }
};
运行结果:


【基于Java的解法】关于Java解法的细节知识,请见我的另一篇博客。
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
public class Solution {
    
    public List<List<Integer>> pathSum(TreeNode root, int sum) 
    {
	   List<List<Integer>> result=new ArrayList<List<Integer>>();//List接口变量用的ArrayList类对象实例化
	   List<Integer> temp=new ArrayList<Integer>();
	   
	   if(root==null)return result;
	   DFS(result,temp,root,sum);
	   return result;
    }
    
    void DFS(List<List<Integer>> result,List<Integer> temp,TreeNode root,int sum)
    {
	   if(root==null)return;
	   if(root.left==null&&root.right==null)
	   {
		   temp.add(root.val);
		   if(sumOfPath(temp)==sum)
			   result.add(new ArrayList(temp));//一定要注意
		   temp.remove(temp.size()-1);
		   return;
	   }
	   else
	   {
		   temp.add(root.val);
		   DFS(result,temp,root.left,sum);
		   DFS(result,temp,root.right,sum);
		   temp.remove(temp.size()-1);
	   }
   }
   
   int sumOfPath(List<Integer> temp)
   {
	   int sum=0;
	   for(int i=0;i<temp.size();i++)
	   {
		   sum+=temp.get(i);
	   }
	   return sum;
   }
}

运行结果:











  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
### 回答1: 可以使用Java中的排序功能来实现。可以使用Arrays.sort()函数,将列表中的元素按照字母顺序排序,或者使用Collections.sort()函数,将列表中的元素按用户指定的排序规则排序。 ### 回答2: 为了实现LeetCode 2561题(Rearranging Fruits)的要求,需要使用Java编程语言。主要思路是遍历给定的水果数组,同时用一个哈希表来记录每个水果出现的次数。然后根据题目要求,重新排列水果使得相同类型的水果尽可能接近,并且按照出现次数的非递增顺序排序。 具体实现步骤如下: 1. 创建一个HashMap来存储每个水果的出现次数。遍历给定的水果数组,如果该水果已经存在于HashMap中,则将其出现次数加1;否则,将该水果添加到HashMap,并将其出现次数初始化为1。 2. 创建一个ArrayList来存储已经排列好的水果。通过HashMap的entrySet方法获取到每种水果和它的出现次数,然后将这些entry按照出现次数的非递增顺序进行排序。 3. 遍历排序好的entry集合,根据每个水果的出现次数,在ArrayList中连续添加相应数量的水果。 4. 返回排列好的水果数组。 以下是Java代码的示例实现: ```java import java.util.*; class Solution { public String[] rearrange(String[] fruits) { HashMap<String, Integer> fruitCountMap = new HashMap<>(); // 统计每个水果的出现次数 for (String fruit : fruits) { if (fruitCountMap.containsKey(fruit)) { fruitCountMap.put(fruit, fruitCountMap.get(fruit) + 1); } else { fruitCountMap.put(fruit, 1); } } ArrayList<Map.Entry<String, Integer>> sortedEntries = new ArrayList<>(fruitCountMap.entrySet()); // 根据出现次数进行非递增排序 Collections.sort(sortedEntries, new Comparator<Map.Entry<String, Integer>>() { public int compare(Map.Entry<String, Integer> entry1, Map.Entry<String, Integer> entry2) { return entry2.getValue().compareTo(entry1.getValue()); } }); ArrayList<String> rearrangedFruits = new ArrayList<>(); // 根据出现次数连续添加水果 for (Map.Entry<String, Integer> entry : sortedEntries) { String fruit = entry.getKey(); int count = entry.getValue(); for (int i = 0; i < count; i++) { rearrangedFruits.add(fruit); } } return rearrangedFruits.toArray(new String[0]); } } ``` 使用以上代码,可以对给定的水果数组进行重新排列,使得相同类型的水果尽可能接近,并且按照出现次数的非递增顺序进行排序。返回的结果就是排列好的水果数组。 ### 回答3: 题目要求将一个字符串中的水果按照特定规则重新排列。我们可以使用Java来实现这个问题。 首先,我们需要定义一个函数来解决这个问题。 ```java public static String rearrangeFruits(String fruits) { // 将字符串转换为字符数组方便处理 char[] fruitArray = fruits.toCharArray(); // 统计每种水果的数量 int[] fruitCount = new int[26]; for (char fruit : fruitArray) { fruitCount[fruit - 'a']++; } // 创建一个新的字符数组来存储重新排列后的结果 char[] rearrangedFruitArray = new char[fruitArray.length]; // 逐个将水果按照规则放入新数组中 int index = 0; for (int i = 0; i < 26; i++) { while (fruitCount[i] > 0) { rearrangedFruitArray[index++] = (char) ('a' + i); fruitCount[i]--; } } // 将字符数组转换为字符串并返回 return new String(rearrangedFruitArray); } ``` 上述代码中,我们首先将字符串转换为字符数组,并使用一个长度为26的数组来统计每一种水果的数量。然后,我们创建一个新的字符数组来存储重新排列后的结果。 接下来,我们利用双重循环将每一种水果按照规则放入新数组中。最后,我们将字符数组转换为字符串并返回。 例如,如果输入字符串为`"acbba"`,则经过重新排列后,输出结果为`"aabbc"`。 这样,我们就用Java实现了题目要求的功能。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jin_Kwok

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值