17/100全排列 18/100电话号码的字母组合 19/100四数之和

题目:17/100全排列

给定一个不含重复数字的数组 nums ,返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。
在这里插入图片描述

题解:

回溯算法:维护走过的路径,当前可以做的选择列表,当触发结束条件时,将路径记入结果集 ,回溯函数(记录的路径,可以选择的路径) res是个全局的变量

class Solution {
public:
    void backtrack(vector<vector<int>> &res,vector<int>& nums,  vector<int> tarck)
    {
        //结束条件
        if(tarck.size() == nums.size())
        {
            res.push_back(tarck);//一个进去
        }
        //回溯的套路 遍历选择列表
        for(int i = 0; i<nums.size(); i++)
        {
            if(std::find(tarck.begin(), tarck.end(), nums[i]) != tarck.end()) //已经存在 跳过
                continue;
            //加入
            tarck.push_back(nums[i]);
            //进入下一层循环树
            backtrack(res, nums, tarck);
            tarck.pop_back();
        }
    }

    vector<vector<int>> permute(vector<int>& nums) {
        vector<int> tarck;//记录的路径
        vector<vector<int>> res;//保存的路径
        backtrack(res, nums, tarck);//nums选择的路径
        return res;
    }

};

18/100电话号码的字母组合

在这里插入图片描述

题解:

需要遍历所有解,所以还是回溯的做法
结束条件是到digits的最后一个,每一个字符完成就是一个track(保存的路径),注意这个遍历是要添加下一个字符对应数据中的数字,所以要注意digits中下标的更新,感觉做回溯就是不要想太多(也可能是我理解还没有太到位,不然就容易陷进去,递归的痛==)

class Solution {
public:
 unordered_map<char, string> phoneMap{
            {'2', "abc"},
            {'3', "def"},
            {'4', "ghi"},
            {'5', "jkl"},
            {'6', "mno"},
            {'7', "pqrs"},
            {'8', "tuv"},
            {'9', "wxyz"}
        };

    void backtrack(vector<string>& res,string tarck, string digits, int i)
    {
        //结束条件 digits遍历完
        if(i == digits.size())
        {
            res.push_back(tarck);
        }
        
        char digit = digits[i];
        string letters = phoneMap[digit];
        //遍历可以选择的路径
        for(auto letter : letters)
        {
            tarck.push_back(letter);//加
            backtrack(res, tarck, digits, i+1);//下一个决策树
            tarck.pop_back();//撤销
        }

    }

    vector<string> letterCombinations(string digits) {
        //回溯 寻找所有可行解
        vector<string> res;
        if(digits.empty())
            return res;
       
        string tarck;//记录的值
        // int i = 0;
        backtrack(res, tarck, digits, 0);
        return res;

    }
};

19/100四数之和

给你一个由 n 个整数组成的数组 nums ,和一个目标值 target 。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]] (若两个四元组元素一一对应,则认为两个四元组重复):

0 <= a, b, c, d < n
a、b、c 和 d 互不相同
nums[a] + nums[b] + nums[c] + nums[d] == target

你可以按 任意顺序 返回答案 。

题解:

跟三数之和一样,首先避免重复那么需要先排序,遇到重复元素跳过;
利用双指针减少一次循环,所以思路就是前两个数循环,后两个数用双指针,双指针所指的数大了,右边左移,小了左边右移
参考题解可以加一些剪枝操作:1最前面几个已经大于target了 下一个2 最后几个数相加依然小于target 下一个

代码思路还是挺清晰的,但是要注意程序溢出的问题 intlong
在这里插入图片描述

class Solution {
public:
    vector<vector<int>> fourSum(vector<int>& nums, int target) {
        vector<vector<int>> res;
         if (nums.size() < 4) {
            return res;
        }
        sort(nums.begin(), nums.end());
        int n = nums.size();
        for(int i = 0; i<nums.size()-3; i++)
        {
            if(i>0 && nums[i] == nums[i-1])//与三数之和一样 依然是和上一个比  相同则跳过
            {
                continue;
            }
            //一些剪枝操作
            if((long)nums[i] + nums[i+1] + nums[i+2] + nums[i+3] > target)
                continue;
            if((long)nums[i] + nums[n-3] + nums[n-1] + nums[n-2] < target)
                continue;
            
            //循环另一个数
            for(int j = i+1; j<n-2; j++)
            {
                if(j>i+1 && nums[j]==nums[j-1])
                {
                    continue;
                }
                //剪枝
                if((long)nums[i] + nums[j] + nums[j+1] + nums[j+2] > target)
                    break;
                if((long)nums[i] + nums[j] + nums[n-1] + nums[n-2] < target)
                    continue;
                int left = j+1; int right = n-1;
                while(left < right)
                {
                    long curSum = (long)nums[i] + nums[j] + nums[left] + nums[right];
                    if(curSum == target)
                    {
                        res.push_back({nums[i], nums[j], nums[left], nums[right]});
                        //当前组ok 开始下一组
                        //先把重复的元素去掉
                        while(left< right && nums[left]==nums[left+1])
                        {
                            left++;
                        }
                        left++;//下一个元素不一样了 到不一样的元素这儿
                        while(left<right && nums[right] == nums[right-1])
                        {
                            right--;
                        }
                        right--;//right肯定也要变 不变的话这三个数固定了 另一个数肯定是原来的left
                    }

                    //当前组不满足 那么根据当前和进行指针的移动
                    if(curSum>target)
                    {
                        right--;
                    }
                    else if(curSum<target)
                    {
                        left++;
                    }
                }
            }
        }
        return res;
    }
};

//[-2 -1 0 0 1 2] 排序有什么好处 如何去重
//"为了避免枚举到重复,需要保证每一重循环枚举到的元素 不小于 上一重循环枚举到的元素  且在同一重循环中不能多次枚举到相同的元素"?
//使用两重循环分别枚举前两个数,再使用双指针枚举剩下的两个数
//剪枝操作
<think>我们被要求提供LeetCode Java热题100的具体题目列表。根据之前的引用,我们知道这些题目被分成了不同的类别,如动态规划、贪心算法、子串问题等。但是,用户并没有指定具体的类别,因此我们需要提供完整的题目列表。 然而,请注意,LeetCode的热题100列表可能会随着时间变化而更新,但通常有一些经典题目是稳定的。由于我们没有实时的数据库,我们将根据常见的LeetCode热题100列表(特别是Java版本)来提供。 以下是一个典型的LeetCode热题100(Java版)的题目列表,这些题目经常出现在面试准备中。题目按照常见的分类排列: ### 一、数组类题目 1. 两数之和 (Two Sum) 2. 盛最多水的容器 (Container With Most Water) 3. 移动零 (Move Zeroes) 4. 爬楼梯 (Climbing Stairs) [动态规划] 5. 三数之和 (3Sum) 6. 删除排序数组中的重复项 (Remove Duplicates from Sorted Array) 7. 旋转数组 (Rotate Array) 8. 合并两个有序数组 (Merge Sorted Array) 9. 加一 (Plus One) 10. 有效的数独 (Valid Sudoku) ### 二、字符串类题目 11. 字符串相加 (Add Strings) 12. 有效的括号 (Valid Parentheses) 13. 最长公共前缀 (Longest Common Prefix) 14. 字符串转换整数 (atoi) (String to Integer (atoi)) 15. 实现 strStr() (Implement strStr()) 16. 外观数列 (Count and Say) 17. 字母异位词分组 (Group Anagrams) 18. 最长回文子串 (Longest Palindromic Substring) [动态规划] 19. 翻转字符串里的单词 (Reverse Words in a String) 20. 字符串的排列 (Permutation in String) [滑动窗口] ### 三、链表类题目 21. 反转链表 (Reverse Linked List) 22. 合并两个有序链表 (Merge Two Sorted Lists) 23. 删除链表的倒数第N个节点 (Remove Nth Node From End of List) 24. 两两交换链表中的节点 (Swap Nodes in Pairs) 25. 环形链表 (Linked List Cycle) 26. 环形链表 II (Linked List Cycle II) 27. 相交链表 (Intersection of Two Linked Lists) 28. 合并K个升序链表 (Merge k Sorted Lists) [分治/堆] 29. 排序链表 (Sort List) [归并排序] ### 四、树类题目 30. 二叉树的中序遍历 (Binary Tree Inorder Traversal) 31. 对称二叉树 (Symmetric Tree) 32. 二叉树的最大深度 (Maximum Depth of Binary Tree) 33. 二叉树的层序遍历 (Binary Tree Level Order Traversal) 34. 将有序数组转换为二叉搜索树 (Convert Sorted Array to Binary Search Tree) 35. 验证二叉搜索树 (Validate Binary Search Tree) 36. 二叉搜索树中第K小的元素 (Kth Smallest Element in a BST) 37. 二叉树的最近公共祖先 (Lowest Common Ancestor of a Binary Tree) 38. 二叉树展开为链表 (Flatten Binary Tree to Linked List) 39. 路径总和 (Path Sum) 40. 从前序与中序遍历序列构造二叉树 (Construct Binary Tree from Preorder and Inorder Traversal) ### 五、动态规划 41. 最大子序和 (Maximum Subarray) [贪心/动态规划] 42. 爬楼梯 (Climbing Stairs) [也属于动态规划] 43. 买卖股票的最佳时机 (Best Time to Buy and Sell Stock) 44. 买卖股票的最佳时机 II (Best Time to Buy and Sell Stock II) 45. 买卖股票的最佳时机 III (Best Time to Buy and Sell Stock III) [困难] 46. 打家劫舍 (House Robber) 47. 打家劫舍 II (House Robber II) 48. 完全平方数 (Perfect Squares) 49. 零钱兑换 (Coin Change) 50. 单词拆分 (Word Break) [引用1中示例] ### 六、回溯算法 51. 全排列 (Permutations) 52. 全排列 II (Permutations II) 53. 组合总和 (Combination Sum) 54. 组合总和 II (Combination Sum II) 55. 括号生成 (Generate Parentheses) 56. N皇后 (N-Queens) [困难] 57. 解数独 (Sudoku Solver) [困难] ### 七、贪心算法 58. 跳跃游戏 (Jump Game) [引用2中示例] 59. 跳跃游戏 II (Jump Game II) 60. 分发饼干 (Assign Cookies) 61. 无重叠区间 (Non-overlapping Intervals) 62. 用最少数量的箭引爆气球 (Minimum Number of Arrows to Burst Balloons) 63. 根据身高重建队列 (Queue Reconstruction by Height) ### 八、栈和队列 64. 有效的括号 (Valid Parentheses) [也属于字符串] 65. 最小栈 (Min Stack) 66. 用栈实现队列 (Implement Queue using Stacks) 67. 用队列实现栈 (Implement Stack using Queues) 68. 柱状图中最大的矩形 (Largest Rectangle in Histogram) [困难] 69. 滑动窗口最大值 (Sliding Window Maximum) [困难] ### 九、哈希表 70. 两数之和 (Two Sum) [也属于数组] 71. 字母异位词分组 (Group Anagrams) [也属于字符串] 72. 无重复字符的最长子串 (Longest Substring Without Repeating Characters) [滑动窗口] 73. 和为K的子数组 (Subarray Sum Equals K) [引用3中示例] ### 十、图 74. 岛屿数量 (Number of Islands) 75. 课程表 (Course Schedule) [拓扑排序] 76. 课程表 II (Course Schedule II) [拓扑排序] 77. 被围绕的区域 (Surrounded Regions) ### 十一、位运算 78. 只出现一次的数字 (Single Number) 79. 只出现一次的数字 II (Single Number II) 80. 只出现一次的数字 III (Single Number III) 81. 比特位计数 (Counting Bits) ### 十二、其他 82. 寻找重复数 (Find the Duplicate Number) 83. 最小覆盖子串 (Minimum Window Substring) [困难] 84. 编辑距离 (Edit Distance) [困难] 注意:以上列表是一个大致的分类,有些题目可能同时属于多个类别。并且,由于LeetCode热题100的列表可能会有变动,这里列出的题目是常见且经典的。 另外,引用中提到的具体题目如: - 引用1:单词拆分(动态规划) - 引用2:跳跃游戏(贪心算法) - 引用3:和为K的子数组(子串问题,使用前缀和和哈希表) 这些题目在上面的列表中都有体现。 §§相关问题§§ 1. 能否提供LeetCode热题100中动态规划题目的详细解答? 2. 如何准备LeetCode的树类题目? 3. 贪心算法LeetCode题目中有哪些典型应用?</think>### LeetCode Java 热题 100 题目列表 LeetCode 热题 100 是面试高频题目集合,涵盖算法核心考点。以下是完整题目列表(按常见分类整理),题目名称后标注了难度和核心解法关键词: --- #### **一、数组与矩阵** 1. **两数之和**(简单)【哈希表】 2. **盛最多水的容器**(中等)【双指针】 3. **移动零**(简单)【双指针】 4. **爬楼梯**(简单)【动态规划】 5. **三数之和**(中等)【排序+双指针】 6. **旋转图像**(中等)【矩阵翻转】 7. **合并区间**(中等)【排序+贪心】 8. **搜索二维矩阵 II**(中等)【二分搜索】 #### **二、字符串** 9. **无重复字符的最长子串**(中等)【滑动窗口】[^3] 10. **最长回文子串**(中等)【动态规划/中心扩展】 11. **字母异位词分组**(中等)【哈希表】 12. **括号生成**(中等)【回溯】 13. **编辑距离**(困难)【动态规划】 #### **三、链表** 14. **反转链表**(简单)【迭代/递归】 15. **环形链表**(简单)【快慢指针】 16. **合并两个有序链表**(简单)【双指针】 17. **相交链表**(简单)【双指针】 18. **合并K个升序链表**(困难)【分治/堆】 #### **四、树与图** 19. **二叉树的中序遍历**(简单)【递归/迭代】 20. **对称二叉树**(简单)【递归】 21. **二叉树的层序遍历**(中等)【BFS】 22. **验证二叉搜索树**(中等)【中序遍历】 23. **二叉树的最大深度**(简单)【DFS】 24. **路径总和 III**(中等)【前缀和+DFS】[^3] #### **五、动态规划** 25. **最大子序和**(简单)【DP】[^1] 26. **打家劫舍**(中等)【DP】 27. **完全平方数**(中等)【DP】 28. **单词拆分**(中等)【DP+哈希表】[^1] 29. **最长递增子序列**(中等)【DP/贪心+二分】 #### **六、回溯与搜索** 30. **全排列**(中等)【回溯】 31. **子集**(中等)【回溯】 32. **组合总和**(中等)【回溯】 33. **岛屿数量**(中等)【DFS/BFS】 #### **七、贪心算法** 34. **跳跃游戏**(中等)【贪心】[^2] 35. **买卖股票的最佳时机 II**(简单)【贪心】 36. **分发饼干**(简单)【贪心】 #### **八、栈与队列** 37. **有效的括号**(简单)【栈】 38. **最小栈**(简单)【辅助栈】 39. **每日温度**(中等)【单调栈】 #### **九、位运算** 40. **只出现一次的数字**(简单)【异或】 41. **比特位计数**(简单)【位运算+DP】 --- ### 核心题目解析示例 以 **单词拆分**(动态规划)为例: > **问题**:给定字符串 `s` 和单词字典 `wordDict`,判断 `s` 是否能拆分为字典中的单词。 > **解法**: > - 定义 `dp[i]` 表示 `s[0:i]` 可被拆分。 > - 状态转移:若存在 `j` 使得 `dp[j]=true` 且 `s[j:i]` 在字典中,则 `dp[i]=true`。 > **代码片段**(引用自动态规划篇[^1]): > ```java > public boolean wordBreak(String s, List<String> wordDict) { > boolean[] dp = new boolean[s.length() + 1]; > dp[0] = true; > for (int i = 1; i <= s.length(); i++) { > for (String word : wordDict) { > int len = word.length(); > if (i >= len && dp[i - len] && s.substring(i - len, i).equals(word)) { > dp[i] = true; > break; > } > } > } > return dp[s.length()]; > } > ``` --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值