LeetCode几道经典题
1. 数组的全排列:
回溯法
class Solution {
public List<List<Integer>> permute(int[] nums) {
LinkedList<List<Integer>> res = new LinkedList<List<Integer>>();
if (nums == null || nums.length == 0)
return res;
Helper(res, new LinkedList<Integer>(), nums, new HashSet<Integer>());
return res;
}
private void Helper(List<List<Integer>> res, List<Integer> curlist, int[] nums,
HashSet<Integer> set){
if (curlist.size() == nums.length)
res.add(new LinkedList<Integer>(curlist));
else{
for (int i = 0; i < nums.length; i++){ //对每个数而言
if (set.contains(nums[i]))
continue;
//加数
curlist.add(nums[i]);
set.add(nums[i]);
Helper(res, curlist, nums, set); //下层的执行完,要把刚刚加进的数字弹出
//删数
set.remove(nums[i]);
int last = curlist.size() - 1;
curlist.remove(last);
}
}
}
}
class Solution {
public List<List<Integer>> permute(int[] nums) {
ArrayList<List<Integer>> res = new ArrayList<List<Integer>>();
if (nums == null || nums.length == 0)
return res;
Helper(nums, res, new ArrayList<Integer>(), new HashSet<Integer>());
return res;
}
private void Helper(int[] nums, ArrayList<List<Integer>> res, ArrayList<Integer> curlist,
HashSet<Integer> set){
if (nums.length == curlist.size())
res.add(new ArrayList<Integer>(curlist));
else{
for (int i = 0; i < nums.length; i++){
if (set.contains(nums[i]))
continue;
set.add(nums[i]);
curlist.add(nums[i]);
Helper(nums, res, curlist, set);
set.remove(nums[i]);
curlist.remove(curlist.size() - 1);
}
}
}
}
2. 去重的全排列:
先排序 然后只需要在每个元素入数组之前判断:这个索引之前没用过&&这个数和上个数不一样
class Solution {
public List<List<Integer>> permuteUnique(int[] nums) {
if (nums == null || nums.length == 0)
return null;
Arrays.sort(nums);
List<List<Integer>> res = new ArrayList<List<Integer>>();
Helper(nums, new boolean[nums.length], new LinkedList<Integer>(), res);
return res;
}
private void Helper(int[] nums, boolean[] used, List<Integer> curlist, List<List<Integer>> res){
if (curlist.size() == nums.length)
res.add(new ArrayList<Integer>(curlist));
else{
int pre = nums[0] - 1; //这个目的: 记录前一个数
for (int idx = 0; idx < nums.length; idx ++){
if (used[idx] == false && (nums[idx] != pre)) {
//索引没被用过,而且索引上的数字和前一个数不一样
pre = nums[idx];
curlist.add(nums[idx]);
used[idx] = true;
Helper(nums, used, curlist, res);
curlist.remove(curlist.size() - 1);
used[idx] = false;
}
}
}
}
}
class Solution {
public List<List<Integer>> permuteUnique(int[] nums) {
if (nums == null || nums.length == 0)
return null;
Arrays.sort(nums);
ArrayList<List<Integer>> res = new ArrayList<List<Integer>>();
Helper(res, nums, new boolean[nums.length], new ArrayList<Integer>());
return res;
}
private void Helper(ArrayList<List<Integer>> res, int[] nums, boolean[] use,
ArrayList<Integer> curlist){
if (curlist.size() == nums.length)
res.add(new ArrayList<Integer>(curlist));
else{
int pre = nums[0] - 1;
for (int i = 0; i < nums.length; i++){
if (use[i] == false && pre != nums[i]){
pre = nums[i];
use[i] = true;
curlist.add(nums[i]);
Helper(res, nums, use, curlist);
curlist.remove(curlist.size() - 1); //往上回溯时候 去掉后面的尾巴
use[i] = false;
}
}
}
}
}
3. 最长回文串:
class Solution {
public int longestPalindrome(String s) {
if(s == null || s.length() == 0)
return 0;
int[] count = new int[128];
int res = 0;
for (char c : s.toCharArray()){
count[c] ++;
}
for (int val : count){
res += val/2 *2;
if (val%2 == 1 && res%2 == 0) //如果想当中心
res++;
}
return res;
}
}
4. 最长回文子串:
中心拓展法,对每个字母进行中心拓展。
class Solution {
public String longestPalindrome(String s) {
if (s == null || s.length() < 1)
return "";
int start = 0, end = 0;
int len = 0;
for(int i = 0; i < s.length(); i++){
int len1 = expand(s, i, i);
int len2 = expand(s, i, i+1);
len = Math.max(len1, len2);
if (len > (end - start)){
start = i - (len - 1)/2;
end = i + (len/2);
}
}
return s.substring(start,end + 1);
}
private int expand(String s, int l, int r){
int i = l, j = r;
while(i >= 0 && j < s.length() && s.charAt(i) == s.charAt(j)){
i --;
j ++;
}
return j - i - 1;
}
}
5. 二叉树展开为链表
后序递归,先右后左。
class Solution {
TreeNode pre = null;
public void flatten(TreeNode root) {
if (root == null)
return;
flatten(root.right);
flatten(root.left);
root.right = pre;
root.left = null;
pre = root;
}
}
6. 最长递增子序列:
动态规划,
public class Solution {
public int lengthOfLIS(int[] nums) {
if (nums.length == 0) {
return 0;
}
int[] dp = new int[nums.length];
dp[0] = 1;
int maxans = 1;
for (int i = 1; i < dp.length; i++) {
int maxval = 0;
for (int j = 0; j < i; j++) { //对i之前的数遍历:如果i比j上的数大,那就看maxval能不能取更大的
if (nums[i] > nums[j]) {
maxval = Math.max(maxval, dp[j]);
}
}
dp[i] = maxval + 1;
maxans = Math.max(maxans, dp[i]); //每个i结束,都看看能不能当最大的
}
return maxans;
}
}
//我的方法:
class Solution {
public int lengthOfLIS(int[] nums) {
if (nums == null || nums.length == 0)
return 0;
int[] dp = new int[nums.length];
dp[0] = 1;
int res = 1;
for (int i = 1; i < nums.length; i++){
int maxFori = 0;
for (int j = 0; j < i; j++){
if(nums[i] > nums[j])
maxFori = Math.max(maxFori, dp[j]);
}
dp[i] = maxFori + 1;
res = Math.max(res, dp[i]);
}
return res;
}
}
7. 最长公共子数组:
从后往前
class Solution {
public int findLength(int[] A, int[] B) {
int ans = 0;
int[][] memo = new int[A.length + 1][B.length + 1];
//从后往前
for (int i = A.length - 1; i >= 0; --i) {
for (int j = B.length - 1; j >= 0; --j) {
if (A[i] == B[j]) {
memo[i][j] = memo[i+1][j+1] + 1;
if (ans < memo[i][j])
ans = memo[i][j];
}
}
}
return ans;
}
}
8. 快速幂:
class Solution {
public double myPow(double x, int n) {
long N = n;
if (N < 0) {
x = 1 / x;
N = -N;
}
double ans = 1;
double current_product = x;
for (long i = N; i > 0; i /= 2) {
if ((i % 2) == 1) {
ans = ans * current_product; //注意这里:不管n是奇数还是偶数,都会走这一步,因为最后i都是1,如果n是奇数,那么就在第一步时候多乘个自己
}
current_product = current_product * current_product;
}
return ans;
}
};
9. 合并k个有序链表
使用优先队列
class Solution {
public ListNode mergeKLists(ListNode[] lists) {
if (lists == null || lists.length == 0)
return null;
PriorityQueue<ListNode> qu = new PriorityQueue<>(lists.length, new Comparator<ListNode>() {
@Override
public int compare(ListNode o1, ListNode o2) {
if (o1.val < o2.val) return -1;
else if (o1.val == o2.val) return 0;
else return 1;
}
});
ListNode dummy = new ListNode(0);
ListNode p = dummy;
for (ListNode node: lists){ //先把头放进去
if (node != null)
qu.add(node);
}
//出队 下一个不空入队
while(!qu.isEmpty()){
p.next = qu.poll();
p = p.next;
if (p.next != null) qu.add(p.next);
}
return dummy.next;
}
} 