使用小顶堆,时间复杂度
class Solution {
public int findKthLargest(int[] nums, int k) {
if (nums == null || nums.length == 0) return 0;
PriorityQueue<Integer> queue = new PriorityQueue<>();
for(int i=0;i<nums.length;i++){
if(queue.size()<k){
queue.add(nums[i]);
}else if(queue.peek()<nums[i]){
queue.poll();
queue.add(nums[i]);
}
}
return queue.peek();
}
}
快速排序:
class Solution {
public int findKthLargest(int[] nums, int k) {
if (nums == null || nums.length == 0) return 0;
int left = 0;
int right = nums.length-1;
quickSort(nums,left,right);
return nums[nums.length-k];
}
private void quickSort(int[] nums, int left, int right) {
if(left>right ) return;
int index = getIndex(nums,left,right);
quickSort(nums,left,index-1);
quickSort(nums,index+1,right);
}
private int getIndex(int[] nums, int left, int right) {
int tmp = nums[left];
while (left=tmp){
right--;
}
nums[left] = nums[right];
while (left
class Solution {
public ListNode reverseList(ListNode head) {
if(head==null) return head;
ListNode pre = null;
ListNode cur = head;
while (cur!=null){
ListNode tmp = cur.next;
cur.next = pre;
pre = cur;
cur = tmp;
}
return pre;
}
}
public class Solution {
public ListNode detectCycle(ListNode head) {
ListNode slow = head;
ListNode fast = head;
while (true){
if(fast==null || fast.next==null){
return null;
}
slow = slow.next;
fast = fast.next.next;
if(slow==fast) {
break;
}
}
slow = head;
while (slow!=fast){
slow = slow.next;
fast = fast.next;
}
return slow;
}
}
递归算法:
class Solution {
List<Integer> list = new ArrayList<>();
public List<Integer> inorderTraversal(TreeNode root) {
if(root==null) return list;
dfs(root);
return list;
}
private void dfs(TreeNode root) {
if(root==null) return;
dfs(root.left);
list.add(root.val);
dfs(root.right);
}
}
迭代算法:
class Solution {
List<Integer> list = new ArrayList<>();
public List<Integer> inorderTraversal(TreeNode root) {
if(root==null) return list;
Stack<TreeNode> stack = new Stack<>();
stack.push(root);
while (!stack.isEmpty()){
TreeNode node = stack.pop();
if(node!=null){
if(node.right!=null) stack.push(node.right);
stack.push(node);
stack.push(null);
if(node.left!=null) stack.push(node.left);
}else{
list.add((stack.pop().val);
}
}
return list;
}
}
class Solution {
public int maxDepth(TreeNode root) {
if(root==null) return 0;
int leftDepth = maxDepth(root.left);
int rightDepth = maxDepth(root.right);
return Math.max(leftDepth,rightDepth)+1;
}
}
class Solution {
List<List<Integer>> res = new ArrayList<>();
public List<List<Integer>> levelOrder(TreeNode root) {
if(root==null) return res;
LinkedList<TreeNode> queue = new LinkedList<>();
queue.add(root);
while (!queue.isEmpty()){
int len = queue.size();
ArrayList<Integer> list = new ArrayList();
for(int i=0;i<len;i++){
TreeNode node = queue.pop();
list.add(node.val);
if(node.left!=null) queue.add(node.left);
if(node.right!=null) queue.add(node.right);
}
res.add(list);
}
return res;
}
}
class Solution {
public int mySqrt(int x) {
//一定要设置为long类型的
long start = 1;
long end = x;
while (start+1<end){
long mid = (end-start)/2+start;
if(mid*mid>=x){
end = mid;
}else{
start = mid;
}
}
if(end*end==x) return (int)end;
else return (int) start;
}
}
暴力算法:
class Solution {
public String longestPalindrome(String s) {
if(s.length() == 0) return s;
if(s.length()<2) return s;
int maxLen = 1;
int begin = 0;
//注意的是s到达最后一个字符的前面一个字符
for(int i=0;i<s.length()-1;i++){
//j到达最后一个字符
for(int j=i+1;j<s.length();j++){
if(j-i+1>maxLen && huiwenchuan(s,i,j)){
maxLen = j-i+1;
begin = i;
}
}
}
return s.substring(begin,begin+maxLen);
}
private boolean huiwenchuan(String s,int i, int j) {
//abccba
while (i<j){
if(s.charAt(i)!=s.charAt(j)){
return false;
}
i++;
j--;
}
return true;
}
}
动态规划:
class Solution {
public String longestPalindrome(String s) {
if(s.length()==0) return s;
boolean[][] dp = new boolean[s.length()][s.length()];
int maxLen = 0;
int begin = 0;
for(int j=0;j<s.length();j++){
for(int i=0;i<=j;i++){
dp[i][j]=s.charAt(i)==s.charAt(j) && (j-i<=2 || dp[i+1][j-1]);
if(dp[i][j] && j-i+1>maxLen){
maxLen = j-i+1;
begin = i;
}
}
}
return s.substring(begin,begin+maxLen);
}
}
class Solution {
public int uniquePaths(int m, int n) {
//动态规划:自底向上
//dp[i][j]代表从路径(0,0)到(i,j)的路径数
int[][] dp = new int[m][n];
//初始化第一行
for(int i=0;i<n;i++){
dp[0][i] = 1;
}
//初始化第一列
for(int j=0;j<m;j++){
dp[j][0] = 1;
}
for(int i=1;i<m;i++){
for(int j=1;j<n;j++){
//路径是只能向下走和向右走,那么路径的总数就是左边一格的路径数+上边一格的路径数
//因为与 dp[i-1][j]+ dp[i][j-1]有关,因此需要初始化dp[0][j]和dp[i][0]
dp[i][j] = dp[i-1][j]+ dp[i][j-1];
}
}
return dp[m-1][n-1];
}
}
class Solution {
public int maxSubArray(int[] nums) {
//一般情况下,求最值的问题,都可转换为最优子结构来解决
if(nums.length==0) return 0;
int[] dp = new int[nums.length];
//dp[i]代表前i个字符组成的子数组的最大和
//状态转移:当前这个状态是怎么由前一个状态得到的?
int res = nums[0];
dp[0] = nums[0];
for(int i=1;i<nums.length;i++){
//注意到dp[i]与dp[i-1]有关,因此需要初始化dp[0]
dp[i] = Math.max(dp[i-1]+nums[i],nums[i]);
res = Math.max(res,dp[i]);
}
return res;
}
}
class Solution {
public int longestCommonSubsequence(String text1, String text2) {
if(text1==null || text2==null) return 0;
int m = text2.length();
int n = text1.length();
//dp[i][j]代表text1的前i个字符和text2的前j个字符的最长公共子序列
int[][] dp = new int[m+1][n+1];
dp[0][0] = 0;
for(int i=1;i<=m;i++){
for(int j=1;j<=n;j++){
if(text1.charAt(j-1)==text2.charAt(i-1)){
//写到这儿就要考虑初始化的问题了,初始化dp[0][0]=0;
dp[i][j] = dp[i-1][j-1]+1;
}else{
//写到这儿需要初始化第一行和第一列
dp[i][j] = Math.max(dp[i-1][j],dp[i][j-1]);
}
}
}
return dp[m][n];
}
}
class Solution {
public int minDistance(String word1, String word2) {
//这种题关键在于如何填表,你是怎么填的?先横向填再纵向填,还是先纵向填再横向填
//dp[i][j]代表word1的前i的字符,转成word2的前j个字符需要的最小操作数
int m = word1.length();
int n = word2.length();
int[][] dp = new int[m+1][n+1];
//初始化第一行
for (int i=0;i<=n;i++){
dp[0][i] = i;
}
//初始化第一列
for(int i=0;i<=m;i++){
dp[i][0] = i;
}
for(int i=1;i<=m;i++){
for(int j=1;j<=n;j++){
if(word1.charAt(i-1)==word2.charAt(j-1)){
//写到这儿,去初始化dp[0][0]
dp[i][j] = dp[i-1][j-1];
}else{
//写到这儿去初始化第一行和第一列dp[0][j] 和dp[i][0]
dp[i][j] = Math.min(Math.min(dp[i-1][j-1],dp[i-1][j]),dp[i][j-1])+1;
}
}
}
return dp[m][n];
}
}
class Solution {
public int lengthOfLIS(int[] nums) {
if(nums.length==0) return 0;
int[] dp = new int[nums.length];
int res = 0;
for(int i=0;i<nums.length;i++){
dp[i] = 1;
for(int j=0;j<i;j++){
if(nums[i]>nums[j]){
//注意这儿,容易出错: 2 5 3 7 101 18
dp[i] = Math.max(dp[i],dp[j]+1);
}
}
res = Math.max(res,dp[i]);
}
return res;
}
}
class Solution {
public int maxValue(int[][] grid) {
int m = grid.length;
int n = grid[0].length;
int[][] dp = new int[m][n];
//初始化第一行,只能向右走
for(int i=1;i<m;i++){
dp[i][0] = dp[i-1][0]+grid[i][0];
}
//初始化第一列,只能向下走
for(int i=1;i<n;i++){
dp[0][i] = dp[0][i-1]+grid[0][i];
}
for(int i=1;i<m;i++){
for(int j=1;j<n;j++){
//写到这儿去初始第一行和第一列
dp[i][j] = Math.max(dp[i-1][j],dp[i][j-1])+grid[i][j];
}
}
return grid[m-1][n-1];
}
}
无后向性是指 以前出现状态 和 以前状态的变化过程 不会影响 将来的变化。
dp是自底向上的,因此需要由下面的状态得出当前的状态,也就是说分析前面一个状态到当前状态需要怎么办?
class Solution {
public int maxProfit(int[] prices) {
if(prices.length==0) return 0;
// dp[i][j]代表第i天,股票状态为j时,股票的最大价格
// j=0时代表持股(只能一次买入,因此不能卖出后买入),j=1时代表不持股
int[][] dp = new int[prices.length][2];
dp[0][0] = -prices[0];
dp[0][1] = 0;
for(int i=1;i<prices.length;i++){
dp[i][0] = Math.max(dp[i-1][0],-prices[i]);
dp[i][1] = Math.max(dp[i-1][1],dp[i-1][0]+prices[i]);
}
return dp[prices.length-1][1];
}
}
class Solution {
public int maxProfit(int[] prices) {
if(prices.length==0) return 0;
//dp[i][j]代表第i天时持股状态为j时的最大收益,j=0时代表持股,j=1时代表不持股
int[][] dp = new int[prices.length][2];
dp[0][0] = -prices[0];
dp[0][1] = 0;
for(int i=1;i<prices.length;i++){
dp[i][0] = Math.max(dp[i-1][0],dp[i-1][1]-prices[i]);
dp[i][1] = Math.max(dp[i-1][1],dp[i-1][0]+prices[i]);
}
return dp[prices.length-1][1];
}
}
class Solution {
public int maxProfit(int[] prices) {
if(prices.length==0) return 0;
//dp[i][j]:第i天持股状态为j时的最大利益,j=0代表第一次持股,j=1代表第一次不持股,j=2代表第二次持股,j=3代表第二次不持股
int[][] dp = new int[prices.length][4];
dp[0][0] = -prices[0];
dp[0][1] = 0;
dp[0][2] = -prices[0];
dp[0][3] = 0;
for(int i=1;i<prices.length;i++){
dp[i][0] = Math.max(dp[i-1][0],-prices[i]);
dp[i][1] = Math.max(dp[i-1][1],dp[i-1][0]+prices[i]);
dp[i][2] = Math.max(dp[i-1][2],dp[i-1][1]-prices[i]);
dp[i][3] = Math.max(dp[i-1][3],dp[i-1][2]+prices[i]);
}
return Math.max(dp[prices.length-1][1],dp[prices.length-1][3]);
}
}
模仿0-1背包优化空间复杂度:倒着写可以通过
class Solution {
public int maxProfit(int[] prices) {
if(prices.length==0) return 0;
//dp[i][j]:第i天持股状态为j时的最大利益,j=0代表第一次持股,j=1代表第一次不持股,j=2代表第二次持股,j=3代表第二次不持股
int[] dp = new int[4];
dp[0] = -prices[0];
dp[1] = 0;
dp[2] = -prices[0];
dp[3] = 0;
for(int i=1;i<prices.length;i++){
dp[3] = Math.max(dp[3],dp[2]+prices[i]);
dp[2] = Math.max(dp[2],dp[1]-prices[i]);
dp[1] = Math.max(dp[1],dp[0]+prices[i]);
dp[0] = Math.max(dp[0],-prices[i]);
}
return Math.max(dp [1],dp[3]);
}
}
发现正着写也能通过:
class Solution {
public int maxProfit(int[] prices) {
if(prices.length==0) return 0;
//dp[i][j]:第i天持股状态为j时的最大利益,j=0代表第一次持股,j=1代表第一次不持股,j=2代表第二次持股,j=3代表第二次不持股
int[] dp = new int[4];
dp[0] = -prices[0];
dp[1] = 0;
dp[2] = -prices[0];
dp[3] = 0;
for(int i=1;i<prices.length;i++){
dp[0] = Math.max(dp[0],-prices[i]);
dp[1] = Math.max(dp[1],dp[0]+prices[i]);
dp[2] = Math.max(dp[2],dp[1]-prices[i]);
dp[3] = Math.max(dp[3],dp[2]+prices[i]);
}
return Math.max(dp [1],dp[3]);
}
}
class Solution {
public int maxProfit(int[] prices) {
if(prices.length==0) return 0;
//dp[i][j]代表在第i天股票状态为j时的最大收益,j=0代表持股,j=1代表冷冻,j=2代表不持股
int[][] dp = new int[prices.length][3];
dp[0][0] = -prices[0];
for(int i=1;i<prices.length;i++){
// dp[i][0] = Math.max(dp[i-1][0],Math.max(-prices[i],dp[i-1][2]-prices[i]));
// 因为支持多次买入和卖出,因此可以写成下面,可以不用细分第一次买入和第二次买入
dp[i][0] = Math.max(dp[i-1][0],dp[i-1][2]-prices[i]);
dp[i][1] = dp[i-1][0]+prices[i];
dp[i][2] = Math.max(dp[i-1][2],dp[i-1][1]);
}
return Math.max(dp[prices.length-1][1],dp[prices.length-1][2]);
}
}
class Solution {
public int maxProfit(int[] prices, int fee) {
if(prices.length==0) return 0;
int[][] dp = new int[prices.length][2];
//如果是买入时减去费用: dp[0][0] = -prices[0]-fee
dp[0][0] = -prices[0];
dp[0][1] = 0;
for(int i=1;i<prices.length;i++){
dp[i][0]= Math.max(dp[i-1][0],dp[i-1][1]-prices[i]);
//费用可以在买入时减去,也可以在卖出时减去,上一个状态为卖出时不需要扣除手续费,仔细分析
dp[i][1] = Math.max(dp[i-1][1],dp[i-1][0]+prices[i]-fee);
}
return dp[prices.length-1][1];
}
}
class Solution {
public int coinChange(int[] coins, int amount) {
if(coins.length==0) return 0;
int[] dp = new int[amount+1];
dp[0] = 0;
for(int i=1;i<=amount;i++){
dp[i] = amount+1;
for(int j=0;j<coins.length;j++){
//别忘记等于号
if(i>=coins[j]){
//做到这儿需要给dp[i-coins[j]赋初值,不然会数组越界
dp[i] = Math.min(dp[i-coins[j]]+1,dp[i]);
}
}
}
return dp[amount]==amount+1?-1:dp[amount];
}
}
BFS:
class Solution {
List<Integer> res = new ArrayList<>();
public List<Integer> rightSideView(TreeNode root) {
if(root==null) return res;
LinkedList<TreeNode> queue = new LinkedList<>();
queue.add(root);
while (!queue.isEmpty()){
int len = queue.size();
for(int i=0;i<len;i++){
TreeNode node = queue.poll();
if(i==len-1){
res.add(node.val);
}
if(node.left!=null) queue.add(node.left);
if(node.right!=null) queue.add(node.right);
}
}
return res;
}
}
DFS:
class Solution {
List<Integer> res = new ArrayList<>();
public List<Integer> rightSideView(TreeNode root) {
if(root==null) return res;
dfs(root,0);
return res;
}
private void dfs(TreeNode root, int level) {
if(root==null) return;
//每一层中止加入一个节点,层数增加时,res里面存放的元素的值也在增加
//当层数和res的大小相等时,说明这一层的元素还没有添加进去
if(res.size()==level){
res.add(root.val);
}
//添加完之后让level增加
level++;
dfs(root.right,level);
dfs(root.left,level);
}
}
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode dummy = new ListNode(0);
ListNode fast = dummy;
ListNode slow = dummy;
dummy.next = head;
for(int i=0;i<n;i++){
if(fast==null) return null;
fast = fast.next;
}
while (fast.next!=null){
fast = fast.next;
slow = slow.next;
}
slow.next = slow.next.next;
return dummy.next;
}
}
leetcode不需要保证稳定性:
class Solution {
public int[] exchange(int[] nums) {
if(nums.length==0) return new int[0];
int left = 0;
int right = nums.length-1;
while (left<right){
while (left<right && nums[left]%2==1) left++;
while (left<right && nums[right]%2==0) right--;
int tmp = nums[left];
nums[left] = nums[right];
nums[right] = tmp;
}
return nums;
}
}
剑指Offer需要保证稳定性,用插入排序:
public class Solution {
public void reOrderArray(int [] array) {
if(array.length==0 || array==null) return;
for(int i=1;i< array.length;i++){
int insertValue = array[i];
if(array[i]%2==1){
int insertIndex = i;
while (insertIndex>=1 && array[insertIndex-1]%2==0){
array[insertIndex] = array[insertIndex-1];
insertIndex--;
}
array[insertIndex] = insertValue;
}
}
}
}
class Solution {
int maxDepth = 0;
public int diameterOfBinaryTree(TreeNode root) {
if(root==null) return 0;
dfs(root);
return maxDepth;
}
private int dfs(TreeNode root) {
if(root==null) return 0;
int leftDepth = dfs(root.left);
int rightDepth = dfs(root.right);
maxDepth = Math.max(maxDepth,leftDepth+rightDepth);
return Math.max(leftDepth,rightDepth)+1;
}
}
class Solution {
public boolean isValid(String s) {
//'(',')','{','}','[',']'
if(s.length()==0) return false;
Stack<Character> stack = new Stack<>();
for(int i=0;i<s.length();i++){
if(s.charAt(i)=='('){
stack.push(')');
}else if(s.charAt(i)=='['){
stack.push(']');
}else if(s.charAt(i)=='{'){
stack.push('}');
}else {
if(stack.isEmpty()){
return false;
}
if(stack.pop()!=s.charAt(i)){
return false;
}
}
}
return stack.isEmpty();
}
}
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
if(headA==null || headB==null) return null;
ListNode cur1 = headA;
ListNode cur2 = headB;
while (cur1!=cur2){
if(cur1==null){
cur1 = headB;
}else{
cur1 = cur1.next;
}
if(cur2==null){
cur2 = headA;
}else {
cur2 = cur2.next;
}
}
return cur1;
}
}
一开始想到的暴力方法:
class Solution {
public int[] intersection(int[] nums1, int[] nums2) {
if(nums1.length==0 || nums2.length==0) return new int[0];
HashSet<Integer> set = new HashSet<>();
for(int i=0;i<nums2.length;i++){
for(int j=0;j<nums1.length;j++){
if(nums1[j]==nums2[i]){
set.add(nums1[j]);
}
}
}
int[] arr = new int[set.size()];
int index = 0;
for(Integer value:set){
arr[index++] = value;
}
return arr;
}
}
使用两个Hashset进行优化:判断一个集合中是否含有另一个数组中的元素
看到去重应该首先想到HashSet,判断是否包含也应该想到Hashset和HashMap
class Solution {
public int[] intersection(int[] nums1, int[] nums2) {
if(nums1.length==0 || nums2.length==0) return new int[0];
HashSet<Integer> set = new HashSet<>();
HashSet<Integer> set1 = new HashSet<>();
for(int i=0;i<nums1.length;i++){
set.add(nums1[i]);
}
for(int j=0;j<nums2.length;j++){
if(set.contains(nums2[j])){
set1.add(nums2[j]);
}
}
int[] arr = new int[set1.size()];
int index = 0;
for(Integer value:set1){
arr[index++] = value;
}
return arr;
}
}
class Solution {
List<List<Integer>> res = new ArrayList<>();
public List<List<Integer>> permute(int[] nums) {
if(nums.length==0 || nums==null) return res;
boolean[] used = new boolean[nums.length];
dfs(nums,used,new ArrayList<Integer>());
return res;
}
private void dfs(int[] nums, boolean[] used, ArrayList<Integer> path) {
if(nums.length==path.size()){
res.add(new ArrayList<>(path));
return;
}
for(int i=0;i<nums.length;i++){
if(used[i]) continue;
path.add(nums[i]);
used[i] = true;
dfs(nums,used,path);
path.remove(path.size()-1);
used[i] = false;
}
}
}
class Solution {
List<List<Integer>> res = new ArrayList<>();
public List<List<Integer>> permuteUnique(int[] nums){
if(nums.length==0 || nums==null) return res;
Arrays.sort(nums);
boolean[] used = new boolean[nums.length];
dfs(nums,used,new ArrayList<Integer>());
return res;
}
private void dfs(int[] nums, boolean[] used, ArrayList<Integer> path) {
if(nums.length==path.size()){
res.add(new ArrayList<>(path));
return;
}
for(int i=0;i<nums.length;i++){
if(used[i]) continue;
if(i>0 && nums[i-1]==nums[i] && used[i-1]==false) continue;
path.add(nums[i]);
used[i] = true;
dfs(nums,used,path);
path.remove(path.size()-1);
used[i] = false;
}
}
}
class Solution {
List<List<Integer>> res = new ArrayList<>();
public List<List<Integer>> subsets(int[] nums) {
dfs(nums,new ArrayList<Integer>(),0);
return res;
}
private void dfs(int[] nums, ArrayList<Integer> path, int start) {
res.add(new ArrayList<>(path));
for(int i=start;i<nums.length;i++){
path.add(nums[i]);
//注意是i+1,而不是start+1
dfs(nums,path,i+1);
path.remove(path.size()-1);
}
}
}
class Solution {
List<List<Integer>> res = new ArrayList<>();
public List<List<Integer>> combinationSum(int[] candidates, int target) {
Arrays.sort(candidates);
dfs(candidates,new ArrayList<Integer>(),target,0);
return res;
}
private void dfs(int[] candidates, ArrayList<Integer> path, int target, int start) {
if(target==0){
res.add(new ArrayList<>(path));
return;
}
for(int i=start;i<candidates.length;i++){
if(candidates[i]>target) continue;
path.add(candidates[i]);
target = target-candidates[i];
//里面的数可以重复利用,又因为不能出现223和232这种情况,所以为i,而不是i+1
dfs(candidates,path,target,i);
path.remove(path.size()-1);
target = target+candidates[i];
}
}
}
class Solution {
List<List<Integer>> res = new ArrayList<>();
public List<List<Integer>> combinationSum2(int[] candidates, int target) {
if(candidates==null ||candidates.length==0) return res;
Arrays.sort(candidates);
boolean[] used = new boolean[candidates.length];
dfs(candidates,used,new ArrayList<Integer>(),0,target);
return res;
}
private void dfs(int[] candidates, boolean[] used, ArrayList<Integer> path, int start,int target) {
if(target==0) {
res.add(new ArrayList<>(path));
return;
}
for(int i=start;i<candidates.length;i++){
//每一个数上一层使用后下一层就不能再使用
if(target<candidates[i]) continue;
//防止数组中有重复元素
if(used[i]) continue;
if(i>0 && candidates[i]==candidates[i-1] && used[i-1]==false) continue;
path.add(candidates[i]);
target = target-candidates[i];
used[i] = true;
//i+1可以防止重复利用一个元素,但是其实上面已经保证了,可以使用i和i+1
dfs(candidates,used,path,i+1,target);
path.remove(path.size()-1);
target= target+candidates[i];
used[i] = false;
}
}
}
class Solution {
public int[] twoSum(int[] nums, int target) {
if(nums.length==0) return new int[0];
HashMap<Integer,Integer> map = new HashMap<>();
for(int i=0;i<nums.length;i++){
if(map.containsKey(target-nums[i])){
return new int[]{
i,map.get(target-nums[i])};
}else{
map.put(nums[i],i);
}
}
return new int[0];
}
}
class Solution {
List<List<Integer>> res = new ArrayList<>();
public List<List<Integer>> threeSum(int[] nums) {
if(nums.length==0) return res;
Arrays.sort(nums);
for(int i=0;i<nums.length;i++){
if(nums[i]>0) continue;
//比如:-4,-4,-1,-1,0,1,1,2
if(i>0 && nums[i]==nums[i-1]) continue;
int left = i+1;
int right = nums.length-1;
int sum = 0;
while (left<right){
sum = nums[left]+nums[right]+nums[i];
if(sum==0){
res.add(Arrays.asList(nums[left],nums[right],nums[i]));
while (left<right && nums[left] == nums[left+1]) left++;
while (left<right && nums[right] == nums[right-1]) right--;
left++;
right--;
}else if(sum>0){
right--;
}else {
left++;
}
}
}
return res;
}
}
class Solution {
public int threeSumClosest(int[] nums, int target) {
if(nums.length==0) return 0;
Arrays.sort(nums);
int res = nums[0]+nums[1]+nums[2];
int sum = 0;
for(int i=0;i<nums.length;i++){
int left = i+1;
int right = nums.length-1;
while (left<right){
sum = nums[left]+nums[right]+nums[i];
if(sum<target){
left++;
}else{
right--;
}
if(Math.abs(target-sum)<Math.abs(target-res)){
res = sum;
}
}
}
return res;
}
}
class Solution {
public int findDuplicate(int[] nums) {
if(nums.length==0) return 0;
int i=0;
while (i<nums.length){
if(nums[i]==i){
i++;
continue;
}else{
int temp = nums[i];
nums[i] = nums[temp];
nums[temp] = temp;
}
if(nums[i]==nums[nums[i]]) return nums[i];
}
return -1;
}
}
public class Solution {
// you need to treat n as an unsigned value
public int hammingWeight(int n) {
int res = 0;
while (n!=0){
res += n&1;
n = n>>>1;
}
return res;
}
}
class Solution {
public int longestCommonSubsequence(String text1, String text2) {
int m = text2.length();
int n = text1.length();
int[][] dp = new int[m+1][n+1];
dp[0][0] = 0;
for(int i=1;i<=m;i++){
for(int j=1;j<=n;j++){
if(text1.charAt(j-1)==text2.charAt(i-1)){
dp[i][j] = dp[i-1][j-1]+1;
}else{
dp[i][j] = Math.max(dp[i-1][j],dp[i][j-1]);
}
}
}
return dp[m][n];
}
}
class Solution {
public int maxProfit(int[] prices) {
if(prices.length==0) return 0;
int[][] dp = new int[prices.length][4];
dp[0][0] = -prices[0];
dp[0][1] = 0;
dp[0][2] = -prices[0];
dp[0][3] = 0;
for(int i=1;i<prices.length;i++){
dp[i][0] = Math.max(dp[i-1][0],-prices[i]);
dp[i][1] = Math.max(dp[i-1][1],dp[i-1][0]+prices[i]);
dp[i][2] = Math.max(dp[i-1][2],dp[i-1][1]-prices[i]);
dp[i][3] = Math.max(dp[i-1][3],dp[i-1][2]+prices[i]);
}
return Math.max( dp[prices.length-1][1], dp[prices.length-1][3]);
}
}
class Solution {
public ListNode reverseKGroup(ListNode head, int k) {
ListNode dummy = new ListNode(0);
dummy.next = head;
ListNode pre = dummy;
ListNode end = dummy;
while (end.next!=null){
for(int i=0;i<k && end!=null;i++) end = end.next;
if(end==null) break;
ListNode start = pre.next;
ListNode next = end.next;
end.next = null;
pre.next = reverseList(start);
start.next = next;
pre = start;
end = pre;
}
return dummy.next;
}
private ListNode reverseList(ListNode start) {
ListNode pre = null;
ListNode cur = start;
while (cur!=null){
ListNode tmp = cur.next;
cur.next = pre;
pre = cur;
cur = tmp;
}
return pre;
}
}
这种方法相当于是两两的反转链表:
class Solution {
public ListNode reverseBetween(ListNode head, int m, int n) {
ListNode dummy = new ListNode(0);
dummy.next = head;
ListNode p1 = dummy;
ListNode p2 = head;
for(int i=0;i<m-1;i++){
p1 = p1.next;
p2 = p2.next;
}
ListNode cur = null;
for(int i=0;i<n-m;i++){
cur = p2.next;
p2.next = p2.next.next;
cur.next = p1.next;
p1.next = cur;
}
return dummy.next;
}
}
class Solution {
public ListNode reverseBetween(ListNode head, int m, int n) {
ListNode dummy = new ListNode(0);
dummy.next = head;
ListNode cur = dummy;
ListNode start = head;
for(int i=0;i<m-1;i++){
cur = cur.next;
start = start.next;
}
for(int i=0;i<n-m;i++){
ListNode end = start.next;
ListNode nextStart = start.next.next;
start.next = nextStart;
end.next = cur.next;
cur.next = end;
}
return dummy.next;
}
}
class Solution {
public ListNode swapPairs(ListNode head) {
if(head==null || head.next==null) return head;
ListNode dummy = new ListNode(0);
dummy.next = head;
ListNode cur = dummy;
ListNode start = head;
while (start !=null && start.next !=null){
ListNode end = start.next;
//必须将这个定义出来
ListNode nexeStart = start.next.next;
cur.next = end;
end.next = start;
start.next= nexeStart;
//一定是先让cur=start
cur = start;
start = nexeStart;
}
return dummy.next;
}
}
动态规划:
class Solution {
public int maxProfit(int[] prices) {
if(prices.length==0) return 0;
int[] dp = new int [2];
dp[0] = -prices[0];
dp[1] = 0;
for(int i=1;i<prices.length;i++){
dp[0] = Math.max(dp[0],-prices[i]);
dp[1] = Math.max(dp[1],dp [0]+prices[i]);
}
return dp [1];
}
}
贪心算法:
class Solution {
public int maxProfit(int[] prices) {
if(prices.length==0) return 0;
int profit = 0;
int minPrice =prices[0];
for(int i=0;i<prices.length;i++){
if(prices[i]<minPrice){
minPrice = prices[i];
}
profit = Math.max(profit,prices[i]-minPrice);
}
return profit;
}
}
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if(root.valp.val && root.val>q.val) return lowestCommonAncestor(root.left,p,q);
return root;
}
}
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if(root==null || root==p || root==q) return root;
TreeNode left = lowestCommonAncestor(root.left,p,q);
TreeNode right = lowestCommonAncestor(root.right,p,q);
if(root==null && right==null) return null;
if(left==null) return right;
if(right==null) return left;
return root;
}
}
class Solution {
public void merge(int[] nums1, int m, int[] nums2, int n) {
int i = m-1;
int j = n-1;
int k = m+n-1;
while (i>=0 && j>=0){
if(nums1[i]>=nums2[j]){
nums1[k--] = nums1[i--];
}else{
nums1[k--] = nums2[j--];
}
}
while (j>=0){
nums1[k--] = nums2[j--];
}
}
}
class Solution {
Node head;
Node pre;
public Node treeToDoublyList(Node root) {
if(root==null) return null;
dfs(root);
head.left = pre;
pre.right = head;
return head;
}
private void dfs(Node cur) {
if(cur==null) return;
dfs(cur.left);
if(pre==null){
head = cur;
}else{
pre.right = cur;
}
cur.left = pre;
pre = cur;
dfs(cur.right);
}
}
class Solution {
public int majorityElement(int[] nums) {
int mainNum = 0;
int count = 0;
for(int i=0;i
class Solution {
public boolean isBalanced(TreeNode root) {
if(root==null) return true;
dfs(root);
return Math.abs(dfs(root.left)-dfs(root.right))<=1 && isBalanced(root.left) && isBalanced(root.right);
}
private int dfs(TreeNode root) {
if(root==null) return 0;
int leftDepth = dfs(root.left);
int rightDepth = dfs(root.right);
return Math.max(leftDepth,rightDepth)+1;
}
}
class Solution {
public boolean isPalindrome(ListNode head) {
if(head==null) return true;
ListNode dummy = new ListNode(0);
dummy.next = head;
ListNode fast = dummy;
ListNode slow = dummy;
while (fast!=null && fast.next!=null){
fast = fast.next.next;
slow = slow.next;
}
ListNode cur = slow.next;
slow.next = null;
ListNode pre= null;
while (cur!=null){
ListNode tmp = cur.next;
cur.next = pre;
pre = cur;
cur = tmp;
}
slow = head;
while (pre!=null && slow!=null){
if(pre.val==slow.val){
pre = pre.next;
slow = slow.next;
}else{
return false;
}
}
return true;
}
}
class Solution {
public ListNode deleteDuplicates(ListNode head) {
if(head==null) return null;
ListNode cur = head;
//只需要保证cur.next!=null即可,不需要cur.nxt.next!=null否则最后两个重复的元素删不掉
while (cur.next!=null){
if(cur.val == cur.next.val){
cur.next = cur.next.next;
}else{
cur = cur.next;
}
}
return head;
}
}
class Solution {
public ListNode middleNode(ListNode head) {
if(head==null) return head;
ListNode fast = head;
ListNode slow = head;
while (fast!=null && fast.next!=null){
fast = fast.next.next;
slow = slow.next;
}
return slow;
}
}
class Solution {
public boolean isSameTree(TreeNode p, TreeNode q) {
if(p==null && q==null) return true;
if(p==null || q==null) return false;
return p.val==q.val && isSameTree(p.left,q.left) && isSameTree(p.right,q.right);
}
}
class Solution {
public boolean isSymmetric(TreeNode root) {
if(root==null) return true;
return dfs(root.left,root.right) ;
}
private boolean dfs(TreeNode A, TreeNode B) {
if(A==null && B==null) return true;
if(A==null || B==null) return false;
return A.val==B.val && dfs(A.left,B.right) && dfs(A.right,B.left);
}
}
class Solution {
public TreeNode mirrorTree(TreeNode root) {
if(root==null) return root;
TreeNode tmp = root.left;
root.left = root.right;
root.right = tmp;
mirrorTree(root.left);
mirrorTree(root.right);
return root;
}
}
class Solution {
public TreeNode invertTree(TreeNode root) {
if(root==null) return root;
TreeNode tmp = root.left;
root.left = root.right;
root.right = tmp;
invertTree(root.left);
invertTree(root.right);
return root;
}
}
class Solution {
public boolean isSubStructure(TreeNode A, TreeNode B) {
if(A==null || B==null) return false;
return dfs(A,B) || isSubStructure(A.left,B) || isSubStructure(A.right,B);
}
private boolean dfs(TreeNode A, TreeNode B) {
if(B==null) return true;
if(A==null) return false;
return A.val==B.val && dfs(A.left,B.left) && dfs(A.right,B.right);
}
}
class Solution {
public boolean isSubtree(TreeNode s, TreeNode t) {
if(t==null) return true;
if(s==null) return false;
return dfs(s,t) || isSubtree(s.left,t) || isSubtree(s.right,t);
}
private boolean dfs(TreeNode s, TreeNode t) {
if(s==null && t==null) return true;
if(s==null || t==null) return false;
return s.val==t.val && dfs(s.left,t.left) && dfs(s.right,t.right);
}
}