力扣刷题总结(JAVA)

1、关于Comparable和Comparator

Comparable接口位于java.lang包下,Comparator位于java.util包下。

Comparable接口只提供了一个compareTo()方法,Comparator接口不仅提供了compara()方法,还提供了其他默认方法,如reversed()、thenComparing(),使我们可以按照更多的方式进行排序

如果要用Comparable接口,则必须实现这个接口,并重写comparaTo()方法;但是Comparator接口可以在类外部使用,通过将该接口的一个匿名类对象当做参数传递给Collections.sort()方法或者Arrays.sort()方法实现排序。Comparator体现了一种策略模式,即可以不用要把比较方法嵌入到类中,而是可以单独在类外部使用,这样我们就可有不用改变类本身的代码而实现对类对象进行排序。

9.1Comparable
Collections类中包含很多对实现Collection接口的容器各种操作的静态方法。当然, 其中最长用的莫过于排序了(Collections.sort(List l)。但是当List容器添加的元素对象是属于自己写的类时, 就可能出问题了。
总而言之, 如果你想1个类的对象支持比较(排序), 就必须实现Comparable接口。Comparable 接口内部只有1个要重写的关键的方法。就是 int compareTo(T o) 这个方法返回1个Int数值,

class Student implements Comparable{
    private String name;
    private int ranking;
 
    public Student(String name, int ranking){
        this.name = name;
        this.ranking = ranking;
    } 
 
    public String toString(){
        return this.name + ":" + this.ranking;
    }
 
    public int compareTo(Object o){
        Student s = (Student)(o);
        return this.ranking - s.ranking;
    }
}

9.2Comparator

// 1.对学生集合按年龄进行排序
Collections.sort(stus, new Comparator<Student>() {

	@Override
	public int compare(Student s1, Student s2) {
		// 升序
		//return s1.getAge()-s2.getAge();
		return s1.getAge().compareTo(s2.getAge());
		// 降序
		// return s2.getAge()-s1.getAge();
		// return s2.getAge().compareTo(s1.getAge());
	}
});

// 2.对学生集合按姓名首字母排序
Comparator comparator = Collator.getInstance(Locale.CHINA);
Collections.sort(stus, new Comparator<Student>() {
		
	@Override
	public int compare(Student s1, Student s2) {
		return comparator.compare(s1.getName(), s2.getName());
	}
		
});

BFS模板

https://www.cnblogs.com/jwthong/p/12762326.html

public List<Integer> rightSideView(TreeNode root) {
        List<Integer> res = new ArrayList<>();
        if (root == null) {
            return res;
        }
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        while (!queue.isEmpty()) {
            int size = queue.size();
            for (int i = 0; i < size; i++) {
                TreeNode node = queue.poll();
                if (node.left != null) {
                    queue.offer(node.left);
                }
                if (node.right != null) {
                    queue.offer(node.right);
                }
                if (i == size - 1) {  //将当前层的最后一个节点放入结果列表
                    res.add(node.val);
                }
            }
        }
        return res;
    }

快慢指针

给定一个包含 n + 1 个整数的数组 nums,其数字都在 1 到 n 之间(包括 1 和 n),可知至少存在一个重复的整数。假设只有一个重复的整数,找出这个重复的数。

public int findDuplicate(int[] nums) {
        int fast=0;
        int slow=0;
        while(true){
            fast=nums[nums[fast]];
            slow = nums[slow];
            if(fast==slow)break;
        }
        int k=0;
        while(true){
            slow=nums[slow];
            k=nums[k];
            if(slow==k)break;
        }
        return slow;
    }

二分法查找

static int cha(int target,int[] arr,int low,int high) {
		if(target>arr[high]||target<arr[low]||low>high) {
			return -1;
		}
		int m=(low+high)/2;
		if(arr[m]>target) {
			return cha(target,arr,low,m-1);
		}else if(arr[m]<target){
			return cha(target,arr,m+1,high);
		}else {
			return m;
		}
   }

7.看不懂
给定一个含有正整数和负整数的环形数组 nums。 如果某个索引中的数 k 为正数,则向前移动 k 个索引。相反,如果是负数 (-k),则向后移动 k 个索引。因为数组是环形的,所以可以假设最后一个元素的下一个元素是第一个元素,而第一个元素的前一个元素是最后一个元素。
确定 nums 中是否存在循环(或周期)。循环必须在相同的索引处开始和结束并且循环长度 > 1。此外,一个循环中的所有运动都必须沿着同一方向进行。换句话说,一个循环中不能同时包括向前的运动和向后的运动。

示例 1:

输入:[2,-1,1,2,2]
输出:true
解释:存在循环,按索引 0 -> 2 -> 3 -> 0 。循环长度为 3 。

public boolean circularArrayLoop(int[] nums) {
        int len =nums.length;
		for(int i=0;i<nums.length;i++) {
        	nums[i]=nums[i]%len;
        }
        for(int i=0;i<len;i++){
        	int f=nums[i];
        	if(f>=len)continue;
        	int j=i;
        	int flag = len+i;
        	int last = j;
        	while(nums[j]<len) {
        		if(f*nums[j]<0)break;
        		int next=(j+nums[j]+len)%len;
        		nums[j]=flag;
        		last = j;
        		j=next;
        	}
        	if(nums[j]==flag&&j!=last)return true;
        }
        return false;
    }

二叉搜索树的删除

class Solution {
  /*
  One step right and then always left
  */
  public int successor(TreeNode root) {
    root = root.right;
    while (root.left != null) root = root.left;
    return root.val;
  }

  /*
  One step left and then always right
  */
  public int predecessor(TreeNode root) {
    root = root.left;
    while (root.right != null) root = root.right;
    return root.val;
  }

  public TreeNode deleteNode(TreeNode root, int key) {
    if (root == null) return null;

    // delete from the right subtree
    if (key > root.val) root.right = deleteNode(root.right, key);
    // delete from the left subtree
    else if (key < root.val) root.left = deleteNode(root.left, key);
    // delete the current node
    else {
      // the node is a leaf
      if (root.left == null && root.right == null) root = null;
      // the node is not a leaf and has a right child
      else if (root.right != null) {
        root.val = successor(root);
        root.right = deleteNode(root.right, root.val);
      }
      // the node is not a leaf, has no right child, and has a left child    
      else {
        root.val = predecessor(root);
        root.left = deleteNode(root.left, root.val);
      }
    }
    return root;
  }
}

最大公约数

static int gcd(int a,int b) {
		return b==0?a:gcd(b,a%b);
	}

最小公倍数

static int lcm(int a,int b) {
		return a*b/gcd(a,b);
	}

全排

题目:输入一个字符串,打印出该字符串中字符的所有排列。你可以以任意顺序返回这个字符串数组,但里面不能有重复元素。
示例
输入:s = “abc”
输出:[“abc”,“acb”,“bac”,“bca”,“cab”,“cba”]

解题:对于一个长度为 n 的字符串(假设字符互不重复),其排列共有n×(n−1)×(n−2)…×2×1 种方案。

class Solution {
    List<String> res = new LinkedList<>();
    char[] c;
    public String[] permutation(String s) {
        c = s.toCharArray();
        dfs(0);
        return res.toArray(new String[res.size()]);
    }
    void dfs(int x) {
        if(x == c.length - 1) {//注意这里,只需要到len-1
            res.add(String.valueOf(c)); // 添加排列方案
            return;
        }
        HashSet<Character> set = new HashSet<>();//这里重点:记录重复的(很巧妙)
        for(int i = x; i < c.length; i++) {
            if(set.contains(c[i])) continue; // 重复,因此剪枝
            set.add(c[i]);
            swap(i, x); // 交换,将 c[i] 固定在第 x 位 
            dfs(x + 1); // 开启固定第 x + 1 位字符
            swap(i, x); // 恢复交换
        }
    }
    void swap(int a, int b) {
        char tmp = c[a];
        c[a] = c[b];
        c[b] = tmp;
    }
}

并查集

【问题描述】
给定一个长度为 N 的数组 A = [A1,A2,……,AN],数组中有可能有重复出现 的整数。
现在小明要按以下方法将其修改为没有重复整数的数组。小明会依次修改 A2,A3,··· ,AN。
当修改 Ai 时,小明会检查 Ai 是否在 A1 ∼ Ai−1 中出现过。如果出现过,则 小明会给 Ai 加上 1 ;如果新的 Ai 仍在之前出现过,小明会持续给 Ai 加 1 ,直 到 Ai 没有在 A1 ∼ Ai−1 中出现过。
当 AN 也经过上述修改之后,显然 A 数组中就没有重复的整数了。 现在给定初始的 A 数组,请你计算出最终的 A 数组。
【输入格式】
第一行包含一个整数 N。 第二行包含 N 个整数 A1,A2,··· ,AN 。
【输出格式】
输出 N 个整数,依次是最终的 A1,A2,··· ,AN。
【样例输入】
5
2 1 1 3 4
【样例输出】
2
1 3 4 5
https://www.cnblogs.com/noKing/p/8018609.html

public class Main{
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		
		
		for(int i=0;i<p.length;i++) {
			p[i]=i;
		}
		
		for(int i=0;i<n;i++) {
			int x = sc.nextInt();
			x = find(x);
			System.out.print(x+" ");
			p[x]=x+1;
		}
		
	}
	static int[] p=new int[1000000];
	//注意注意
	static int find(int x) {
		if(p[x]==x) {
			return x;
		}else {
			p[x]=find(p[x]);//注意这里
			return p[x];
		}
	}
}

组合C(n,m)

static long[][] c = new long[2005][2005];
	static int k=100000007;
	static long c(int n, int m) {
		if (m == 0 || m == n)
			return 1;
		if (c[n][m] != 0)
			return c[n][m];
		return c[n][m] = (c(n - 1, m - 1) + c(n - 1, m)) ;
	}

最长递增子序列

import java.util.Scanner;
 
public class Main{
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in); 
		int n = sc.nextInt();
		int[] arr = new int[10002];//arr数组表示输入的序列
		int[] dp = new int[10002];//dp数组中存放上升序列的长度,dp[i]表示以arr[i]结尾的子序列的最大长度
		for(int i = 1;i <= n;i++) {//输入序列
			int a = sc.nextInt();
			arr[i] = a;
		}
		
		int result = -1;//记录dp中最大的值
		
		for(int i = 1;i <= n;i++) {//按顺序计算dp[i]的值
			dp[i] = 1;//假设该子序列中只有arr[i],故长度为1,即其自身成为一个子序列
			for(int j = 1;j < i;j++) {
//如果在i之前有比arr[i]小的数(arr[j]),并且把该数(arr[i])放到以arr[j]结尾的子序列末尾后,
//其长度比当前以arr[i]结尾的子序列长度要长
				if(arr[i] > arr[j] && dp[j] + 1 > dp[i]) {
					dp[i] = dp[j] + 1;//把arr[i]放到以arr[j]结尾的子序列之后,原来的长度+1
				}
			}
			result = Math.max(result, dp[i]);//找出在dp数组中最大的一个,即子序列长度最长的一个
		}
		System.out.println(result);
	}
}
  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值