力扣刷题总结(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;
    }
}

你可能感兴趣的:(力扣刷题总结(JAVA))