面试高频算法题top100(51~60)java实现
51.判断一个链表是否为回文结构
给定一个链表,请判断该链表是否为回文结构。
( 回文是指该字符串正序逆序完全一致。 )
import java.util.*;
public class Solution {
public boolean isPail (ListNode head) {
ListNode temp = head;
int len = 0;
Stack<Integer> stack = new Stack<>();
while(temp!=null){
len +=1;
stack.push(temp.val);
temp = temp.next;
}
len /= 2;
while(len-->0){
if(head.val!=stack.pop())
return false;
head = head.next;
}
return true;
}
}
52.编辑距离(二)
给定两个字符串str1和str2,再给定三个整数ic,dc和rc,分别代表插入、删除和替换一个字符的代价,请输出将str1编辑成str2的最小代价。
import java.util.*;
public class Solution {
public int minEditCost (String str1, String str2, int ic, int dc, int rc) {
int m = str1.length();
int n = str2.length();
int[][] dp = new int[m+1][n+1];
for(int i=1;i<=m;i++)
dp[i][0] = i*dc;
for(int j=1;j<=n;j++)
dp[0][j] = j*ic;
for(int i=1;i<=m;i++){
for(int j=1;j<=n;j++){
if(str1.charAt(i-1)==str2.charAt(j-1))
dp[i][j] = dp[i-1][j-1];
else{
dp[i][j] = Math.min(dp[i-1][j-1]+rc,Math.min(dp[i][j-1]+ic,dp[i-1][j]+dc));
}
}
}
return dp[m][n];
}
}
空间优化为O(n):
import java.util.*;
public class Solution {
public int minEditCost (String str1, String str2, int ic, int dc, int rc) {
int m = str1.length();
int n = str2.length();
int[] dp = new int[n+1];
for(int j=1;j<=n;j++)
dp[j] = j*ic;
for(int i=1;i<=m;i++){
int pre = dp[0];
dp[0] = i*dc;
for(int j=1;j<=n;++j){
int temp = dp[j];
if(str1.charAt(i-1)==str2.charAt(j-1)) dp[j] = pre;
else{
dp[j] = Math.min(pre+rc,Math.min(dp[j-1]+ic,temp+dc));
}
pre = temp;
}
}
return dp[n];
}
}
53.二叉树根节点到叶子节点的所有路径和
给定一个二叉树的根节点root,该树的节点值都在数字 0−9\ 0-9 0−9 之间,每一条从根节点到叶子节点的路径都可以用一个数字表示。
1.该题路径定义为从树的根结点开始往下一直到叶子结点所经过的结点
2.叶子节点是指没有子节点的节点
3.路径只能从父节点到子节点,不能从子节点到父节点
4.总节点数目为n
import java.util.*;
/*
* public class TreeNode {
* int val = 0;
* TreeNode left = null;
* TreeNode right = null;
* }
*/
public class Solution {
public int sumNumbers (TreeNode root) {
int sum = 0;
Stack<TreeNode> Node = new Stack<>();
Stack<Integer> num = new Stack<>();
if(root==null) return 0;
Node.push(root);
num.push(root.val);
while(!Node.empty()){
TreeNode temp = Node.pop();
int t = num.pop();
if(temp.left==null && temp.right==null)
sum += t;
else{
if(temp.left!=null){
Node.push(temp.left);
num.push(t*10 + temp.left.val);
}
if(temp.right!=null){
Node.push(temp.right);
num.push(t*10 + temp.right.val);
}
}
}
return sum;
}
}
54.二叉树中和为某一值的路径(二)
输入一颗二叉树的根节点root和一个整数expectNumber,找出二叉树中结点值的和为expectNumber的所有路径。
1.该题路径定义为从树的根结点开始往下一直到叶子结点所经过的结点
2.叶子节点是指没有子节点的节点
3.路径只能从父节点到子节点,不能从子节点到父节点
4.总节点数目为n
import java.util.ArrayList;
/**
public class TreeNode {
int val = 0;
TreeNode left = null;
TreeNode right = null;
public TreeNode(int val) {
this.val = val;
}
}
*/
public class Solution {
ArrayList<ArrayList<Integer>> res = new ArrayList<>();
public ArrayList<ArrayList<Integer>> FindPath(TreeNode root,int expectNumber) {
search(root,expectNumber,new ArrayList<>());
return res;
}
public void search(TreeNode root,int tar,ArrayList<Integer> list){
if(root==null) return;
tar -= root.val;
list.add(root.val);
if(tar==0 && root.left==null && root.right==null)
res.add(new ArrayList(list));
search(root.left,tar,list);
search(root.right,tar,list);
list.remove(list.size()-1);
tar += root.val;
}
}
55.链表内指定区间反转
import java.util.*;
/*
* public class ListNode {
* int val;
* ListNode next = null;
* }
*/
public class Solution {
public ListNode reverseBetween (ListNode head, int m, int n) {
ListNode pre = new ListNode(-1);
pre.next = head;
ListNode dummy = pre;
int count = 0;
for(int i=1;i<m;i++) {
pre = head;
head = head.next;
}
ListNode start = head;
for(int i=m;i<n;i++){
head = head.next;
}
ListNode next = head.next;
head.next = null;
pre.next = reverse(start);
start.next =next;
return dummy.next;
}
public ListNode reverse(ListNode h1){
ListNode pre = null;
ListNode cur = null;
while(h1!=null){
cur = h1.next;
h1.next = pre;
pre = h1;
h1 = cur;
}
return pre;
}
}
56.不同路径的数目(一)
import java.util.*;
public class Solution {
public int uniquePaths (int m, int n) {
int[][] dp = new int[m][n];
for(int i=0;i<m;i++)
dp[i][0] = 1;
for(int j=0;j<n;j++)
dp[0][j] = 1;
for(int i=1;i<m;i++){
for(int j=1;j<n;j++){
dp[i][j] = dp[i][j-1] + dp[i-1][j];
}
}
return dp[m-1][n-1];
}
}
空间复杂度优化为O(m+n):
import java.util.*;
public class Solution {
public int uniquePaths (int m, int n) {
//矩阵只要有一条边为1,路径数就只有一种了
if(m == 1 || n == 1)
return 1;
//两个分支
return uniquePaths(m - 1, n) + uniquePaths(m, n - 1);
}
}
空间复杂度优化为O(1)且时间复杂度优化为O(n):
import java.util.*;
public class Solution {
public int uniquePaths (int m, int n) {
//防止溢出
long res = 1;
for(int i = 1; i < n; i++)
//根据公式计算
res = res * (m + i - 1) / i;
return (int)res;
}
}
57.合并区间
给出一组区间,请合并所有重叠的区间。请保证合并后的区间按区间起点升序排列。
import java.util.*;
/**
* Definition for an interval.
* public class Interval {
* int start;
* int end;
* Interval() { start = 0; end = 0; }
* Interval(int s, int e) { start = s; end = e; }
* }
*/
public class Solution {
public ArrayList<Interval> merge(ArrayList<Interval> intervals) {
Collections.sort(intervals,new Comparator<Interval>(){
@Override
public int compare(Interval o1,Interval o2){
return o1.start-o2.start;
}
});
ArrayList<Interval> res = new ArrayList<>();
for(int i=0;i<intervals.size();i++){
if(i==0 || intervals.get(i).start>res.get(res.size()-1).end){
res.add(intervals.get(i));
}else{
res.get(res.size()-1).end = Math.max(res.get(res.size()-1).end,intervals.get(i).end);
}
}
return res;
}
}
58.最长公共子序列(二)
给定两个字符串str1和str2,输出两个字符串的最长公共子序列。如果最长公共子序列为空,则返回"-1"。目前给出的数据,仅仅会存在一个最长的公共子序列
import java.util.*;
public class Solution {
/**
* longest common subsequence
* @param s1 string字符串 the string
* @param s2 string字符串 the string
* @return string字符串
*/
public String LCS (String s1, String s2) {
int len1 = s1.length(),len2 = s2.length();
int[][] dp = new int[len1+1][len2+1];
if(len1==0 || len2==0) return "-1";
for(int i=1;i<=len1;i++){
for(int j=1;j<=len2;j++){
if(s1.charAt(i-1)==s2.charAt(j-1))
dp[i][j] = dp[i-1][j-1] + 1;
else
dp[i][j] = Math.max(dp[i-1][j],dp[i][j-1]);
}
}
if(dp[len1][len2]==0) return "-1";
StringBuilder str = new StringBuilder();
while(len1>0 && len2>0){
if(s1.charAt(len1-1)==s2.charAt(len2-1)){
str.append(s1.charAt(len1-1));
len2--;
len1--;
}
else if(dp[len1][len2-1]>dp[len1-1][len2])
len2--;
else
len1--;
}
return str.reverse().toString();
}
}
59.在两个长度相等的排序数组中找到中位数
给定两个递增数组arr1和arr2,已知两个数组的长度都为N,求两个数组中所有数的上中位数。
上中位数:假设递增序列长度为n,为第n/2个数 。
import java.util.*;
public class Solution {
public int findMedianinTwoSortedAray (int[] arr1, int[] arr2) {
int left1=0,right1 = arr1.length-1,left2=0,right2 = arr2.length-1;
while(left1<right1){
int mid1 = left1 + (right1-left1)/2;
int mid2 = left2 + (right2-left2)/2;
int temp = (right1-left1+1)%2==0?1:0;
if(arr1[mid1]==arr2[mid2])
return arr1[mid1];
else if(arr1[mid1]<arr2[mid2]){
left1 = mid1+temp;
right2 = mid2;
}else{
right1 = mid1;
left2 = mid2+temp;
}
}
return Math.min(arr1[left1],arr2[left2]);
}
}片
60.判断一棵二叉树是否为搜索二叉树和完全二叉树
给定一棵二叉树,已知其中的节点没有重复值,请判断该二叉树是否为搜索二叉树和完全二叉树。
import java.util.*;
/*
* public class TreeNode {
* int val = 0;
* TreeNode left = null;
* TreeNode right = null;
* }
*/
public class Solution {
public boolean[] judgeIt (TreeNode root) {
boolean[] res = new boolean[2];
res[0] = Is_search(root);
res[1] = Is_comple(root);
return res;
}
public boolean Is_search(TreeNode root){
ArrayList<Integer> list = new ArrayList<>();
search(root,list);
int pre = Integer.MIN_VALUE;
for(int i:list){
if(i>pre)
pre = i;
else
return false;
}
return true;
}
public void search(TreeNode root,ArrayList<Integer> list){
if(root==null) return;
search(root.left,list);
list.add(root.val);
search(root.right,list);
}
public boolean Is_comple(TreeNode root){
if(root==null) return true;
boolean flag = false;
Queue<TreeNode> que = new LinkedList<>();
que.add(root);
while(!que.isEmpty()){
TreeNode temp = que.poll();
if(flag==true){
if(temp.left!=null || temp.right!=null)
return false;
}
if(temp.left==null && temp.right!=null)
return false;
if(temp.left==null || temp.right==null)
flag = true;
if(temp.left!=null)
que.add(temp.left);
if(temp.right!=null)
que.add(temp.right);
}
return true;
}
}