(1)NC78反转链表
(2)NC140 排序
两种常用排序
用快排实现
public int[] MySort (int[] arr) {
fastSort(arr,0,arr.length-1);
return arr;
}
private void fastSort(int[] arr,int l,int r){
if(l>=r)
return;
int num = arr[r];
int sl = l,sr=r;
while(lnum)r--;
//在填入前一定要进行判断
if(l
用归并法实现
public class Solution {
public int[] MySort (int[] arr) {
// write code here
mergeSort(arr,0,arr.length-1);
return arr;
}
private void mergeSort(int[] arr , int l , int r){
if(l>=r)
return;
int mid = (l+r)>>1;
//分两边继续递归
mergeSort(arr,l,mid);
mergeSort(arr,mid+1,r);
//两边都递归结束,才合并此层
merge(arr,l,mid,r);
}
private void merge(int[] arr,int l,int mid,int r){
int[] t = new int[r-l+1];
int index = 0;
int h1 = l, h2 = mid+1;
while(h1<=mid&&h2<=r){
if(arr[h1]
堆排序
优先队列
(3)NC45 实现二叉树先序,中序和后序遍历
返回形式
public int[][] threeOrders (TreeNode root) {
// 分辨用链表先存储
ArrayList prelist = new ArrayList();
ArrayList inlist = new ArrayList();
ArrayList postlist = new ArrayList();
preOrder(root,prelist);
inOrder(root,inlist);
postOrder(root,postlist);
//再根据链表长创建二维数组
int[][] res = new int[3][prelist.size()];
for(int i=0;i
(4)NC119 最小的K个数
本题可采用分会分治,可大顶堆。大顶堆实现起来更容易。或使用Array自带sort排序
import java.util.*;
public class Solution {
public ArrayList GetLeastNumbers_Solution(int [] input, int k) {
ArrayList res = new ArrayList();
if(k<=0||input.length==0)
return res;
if(input.length<=k){
for(int i =0;i queue = new PriorityQueue((o1,o2)->(o2-o1));
for(int i = 0;i=k){
if(queue.peek()>input[i]){
queue.poll();
queue.offer(input[i]);
}
}
else{
queue.offer(input[i]);
}
}
while(!queue.isEmpty()){
res.add(queue.poll());
}
return res;
}
}
(5)NC15 求二叉树的层序遍历
(6)NC88 寻找第K大
使用快排,有两个注意的点
1、一定记住把,暂存的t放入
2、递归时,范围缩小的操作
public class Solution {
public int findKth(int[] a, int n, int K) {
// write code here
if(n<=0||K>n)
return -1;
sortInt(a,0,n-1,K-1);
return a[K-1];
}
private void sortInt(int[] a, int l,int r,int k){
int t = a[r];
int nl = l,nr=r;
while(nlt)nl++;
if(nl
(7)NC61 两数之和
没便利到一个数,target-当前 若在map中则将(当前值,下标)存入。若存在则找到了和为target的值。
public int[] twoSum (int[] numbers, int target) {
// write code here
Map map = new HashMap();
int[] res = new int[2];
for(int i = 0;i
(8)NC33 合并两个排序的链表
(9)NC76 用两个栈实现队列
(10)NC50 链表中的节点每k个一组翻转
public ListNode reverseKGroup (ListNode head, int k) {
// write code here
//寻找第k个结点。过程中出现null则不反转,直接但会当前链表
ListNode tail = head;
for(int i=0;i
(11) NC19 连续子数组的最大和
sum记录当前和,sum+nextNumber大于nextNumber则将nextNumber加入总和,不然说明不能继续连续,以nextNumber为新起点。
每次计算后都比较更新max
(12)NC41 最长无重复子数组
1、l,r分别指向无重复数组头尾
2、新进加入数组的元素,若map中已存在,则需要重新更新起点。新起点为重复数字的下标的下一个。若此位置小于当先l,则说面重复数字不再当前范围内,故不更新
public int maxLength (int[] arr) {
// write code here
if(arr.length==0)
return 0;
int max = 1;
int l = 0, r=1;
Map map = new HashMap();
map.put(arr[0],0);
while(rl){
l = map.get(arr[r])+1;
}
map.put(arr[r],r);
//每次更新完l,r重新判断是否活得最大长度
if(r-l+1>max){
max=r-l+1;
}
r++;
}
if(r-l>max){
max=r-l;
}
return max;
}
(13)NC4 判断链表中是否有环
当由于后续为null,fast,slow不移动的情况。此时要将其直接置null。不然会世中卡在当前不能后移的结点位置
public boolean hasCycle(ListNode head) {
ListNode slow = head;
ListNode fast = head;
int index = 0;
while(index==0||slow!=fast){
if(slow!=null)
slow=slow.next;
else
slow =null;
if(fast!=null&&fast.next!=null){
fast = fast.next.next;
}
else
fast = null;
index = 1;
}
if(slow==null)
return false;
return true;
}
(14)NC22 合并两个有序的数组
(15)NC3 链表中环的入口结点
(16)NC52 有效括号序列
(17)NC53 删除链表的倒数第n个节点
(18)NC1 大数加法
注意数据类型的选择,当需要一个可变长度的字符串时用StringBuffer
(19)NC14 按之字形顺序打印二叉树
注意如何Collections.reverse用于list集合的反转。Collections.reverse(arr);
不需要通过改变左右孩子入队顺序去实现,只需将需从右到左遍历的行反转
(20)NC127 最长公共子串
dp[i][j]表示字符串str1中第i个字符和str2种第j个字符为最后一个元素所构成的最长公共子串。
如果不相等,那么他们就不能构成公共子串,也就是
dp[i][j]=0;
如果相等,我们还需要计算前面相等字符的个数,其实就是dp[i-1][j-1],所以
dp[i][j]=dp[i-1][j-1]+1;(即其前一位为连续,则长度会增加1,前一位不为联系则此处为开始即0)
在实现是考虑到下表0减一为负。故二维数组i+1相当于i位置
public String LCS (String str1, String str2) {
// write code here
int[][] dp = new int[str1.length()+1][str2.length()+1];
int maxindex = 0;
int maxlength = 0;
//maxindex与maxlength在每次找到相等字符时进行递增。
for(int i = 0;imaxlength){
maxlength=dp[i+1][j+1];
maxindex = i;
}
}else{
dp[i+1][j+1]=0;
}
}
}
return str1.substring(maxindex-maxlength+1,maxindex+1);
}
(21)NC66 两个链表的第一个公共结点
(22)NC40 链表相加(二)
(23)NC102 在二叉树中找到两个节点的最近公共
递归方法:
注:若路径下无匹配则会遍历到叶子结点,一路向上返回null
1、当前结点为空,或与寻找值匹配。则返回当前结点。
对当前结点的左右进行递归,有以下几种情况
left=null right=null 返回null
left为空 返回right(若right不为null则说明其有匹配结点)
right为空 返回left(若left不为null则说明其有匹配结点)
若lef与right均不为空则,说明结果在两侧,则返回当前结点。
public int lowestCommonAncestor (TreeNode root, int o1, int o2) {
// write code here
return dfs(root,o1,o2).val;
}
private TreeNode dfs(TreeNode root, int o1, int o2){
if(root==null||root.val==o1||root.val==o2){
return root;
}
TreeNode left = dfs(root.left,o1,o2);
TreeNode right = dfs(root.right,o1,o2);
if(left==null)
return right;
if(right==null)
return left;
return root;
}
非递归当打实现:
(1)map记录每个结点值对应的父节点值
如何对map进行初始化?采用层遍历,结束标志,map的key中包含o1和o2
(2)先将o1路径记录下来,用set记录,一路向上寻找父节点记录进set,直道不存在父节点(即map中无此key)
从o2向上依次遍历其父节点,若存在于set中则为最近公共结点
public int lowestCommonAncestor (TreeNode root, int o1, int o2) {
// write code here
Map map = new HashMap();
Queue queue = new LinkedList();
map.put(root.val,Integer.MAX_VALUE);
queue.add(root);
while(!map.containsKey(o1)||!map.containsKey(o2)){
TreeNode node = queue.poll();
if(node.left!=null){
queue.offer(node.left);
map.put(node.left.val,node.val);
}
if(node.right!=null){
queue.offer(node.right);
map.put(node.right.val,node.val);
}
}
Set set = new HashSet();
while(map.containsKey(o1)){
set.add(o1);
o1 = map.get(o1);
}
while(!set.contains(o2)){
o2 = map.get(o2);
}
return o2;
}
(24)NC103 反转字符串
这里主要是String几个方法
预将String当成数组操作时 ch=str.toCharArray()
用char[] 生成String 时 new String(ch)
(25)NC38 螺旋矩阵
这里面有两个注意点
1、圈数:取row和col最小值计算圈
2、边界控制:输入下时判断此行,上是都已输入过
输入左时判断此列,右是否已输入过
public ArrayList spiralOrder(int[][] matrix) {
ArrayList arr = new ArrayList();
if(matrix.length==0)
return arr;
int row = matrix.length;
int col = matrix[0].length;
int cir = (row =c;i--)
arr.add(matrix[row-c-1][i]);
//是否输出左行判断
if(c=c+1;i--)
arr.add(matrix[i][c]);
}
return arr;
}
(26)NC65 斐波那契数列
(27)NC17 最长回文子串
方法一:两种情况
偶数以当前位置i,i+1发散寻找
奇数当前位置为中心,i,i发散寻找
public int getLongestPalindrome (String A) {
// write code here
if(A==null||A.length()==0){
return 0;
}
int maxl = Integer.MIN_VALUE;
for(int i = 0;i=0&&r
(28)NC54 三数之和
1、将数组排序
2、i指向元组第一个位置元素,
当i对应值大于0时则说明后面均大于零。可以停止寻找
当i对应值小于0,可转化为将后面的有序数组中两个值的和等于固定值0-num[i]
和大于0-num[i],r减小即指向更小一点儿的数
和小于0-num[i],l增大即指向更大一点儿的数
和与0-num[i]相等,则加入集合
3、可以加入集合,并不能停止寻找合等于0-num[i]的对
但需先去除重复元素,l,r从新的位置开始继续寻找
public ArrayList> threeSum(int[] num) {
ArrayList> res = new ArrayList>();
if(num.length<3)
return res;
Arrays.sort(num);
for(int i = 0;i < num.length-2;i++){
if(num[i]>0)
break;
if(i>0&&num[i-1]==num[i])
continue;
int l = i+1;
int r = num.length-1;
while(l arr = new ArrayList();
arr.add(num[i]);
arr.add(num[l]);
arr.add(num[r]);
res.add(arr);
//去除重复
while(l0-num[i])
r--;
else
l++;
}
}
return res;
}
(29)NC12 重建二叉树
(30)NC91 最长上升子序列(三)
import java.util.*;
public class Solution {
/**
* retrun the longest increasing subsequence
* @param arr int整型一维数组 the array
* @return int整型一维数组
*/
public int[] LIS (int[] arr) {
int[] tail = new int[arr.length];
int[] dp = new int[arr.length];
int len = 0;
//构建dp,dp记录每一位最长升子序列长度
for(int i = 0;i=0;i--){
if(dp[i]==len){
res[--len] = arr[i];
}
}
return res;
}
private int search(int[] tail,int len, int num){
int low=0,high=len-1;
while(low=num)
high=mid;
else
low=mid+1;
}
return high;
}
}
(31)NC32 求平方根
注意处理0,1特殊情况
范围;i<=x/2+1,加1不能省略
(32)NC48 在旋转过的有序数组中寻找目标值
注意二分查找的范围控制
public int search (int[] nums, int target) {
// write code here
int l = 0,r = nums.length-1;
while(l<=r){//等号
int mid = (l+r)/2;
if(nums[mid]==target)return mid;
if(nums[mid]>=nums[l]){//前段有序
if(target>=nums[l]&&targetnums[mid])
l = mid+1;
else
r = mid-1;
}
}
return -1;
}
(33)NC90 包含min函数的栈
(34)NC7 买卖股票的最好时机(一)
从右往左存储目前最小值,计算的总是当前范围内的最小值,故一定符合先买后卖原则
public int maxProfit (int[] prices) {
// write code here
int minprice = Integer.MAX_VALUE;
int ans = 0;
for(int i = 0;ians)
ans = prices[i]-minprice;
}
return ans;
}
(35)JZ38 字符串的排列
每次递归传入当前一组成的字符串,和可以继续组的字符串
public ArrayList Permutation(String str) {
ArrayList result = new ArrayList();
if(str==null||str.length()==0)
return null;
newString(str,"",result);
return result;
}
public void newString(String str,String newstr,ArrayList result){
if(str.length()==0){
if(!result.contains(newstr.toString()))
result.add(newstr.toString());
return ;
}
for(int i = 0;i
(36)NC136 输出二叉树的右视图
(37)NC109 岛屿数量
可以用递归法解决。将一个岛屿的起点进行递归,经历过的填都改为0
// write code here
int sum = 0;
//每遇到一个不为零的值,则说明出现一个岛屿sum++
//从此点为起点,利用递归将此岛屿上的错油都置为0,即记录过就删除
for(int i = 0;i=grid.length||j<0||j>=grid[0].length||grid[i][j]=='0')
return;
grid[i][j] = '0';
dfs(grid,i-1,j);
dfs(grid,i+1,j);
dfs(grid,i,j-1);
dfs(grid,i,j+1);
}
}
(38)NC13 二叉树的最大深度
(39)NC141 判断是否为回文字符串
(40)NC137 表达式求值
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
* 返回表达式的值
* @param s string字符串 待计算的表达式
* @return int整型
*/
public int solve (String s) {
// write code here
Stack snum = new Stack();
Stack sop = new Stack();
Map map = new HashMap();
//建立优先级关系
map.put('-',1);
map.put('+',1);
map.put('*',2);
map.put('(',0);
int index = 0;
while(index='0'){
//因可能超过各位数字,故组合数组。直至找到非数字字符
String str = "";
while(index='0'){
str += s.charAt(index++);
}
int sum = Integer.parseInt(str);
//将数组入栈
snum.push(sum);
}
else{
//计算字符为空直接入栈
if(sop.isEmpty())
sop.push(s.charAt(index));
//输入字符为(直接入栈
else if(s.charAt(index)=='(')
sop.push(s.charAt(index));
//输入字符为),找到一个匹配的(
else if(s.charAt(index)==')'){
//不是(就一致出栈计算
while(sop.peek()!='('){
int num = compute(snum.pop(),snum.pop(),sop.pop());
snum.push(num);
}
//最好将(出战
sop.pop();
}
//输入字符的优先级高于当前栈顶,直接入栈
else if(map.get(s.charAt(index))>map.get(sop.peek()))
sop.push(s.charAt(index));
else{
//输入字符的优先级低或等于当前栈顶,需计算
//特例情况,肯能遇见下一个字符是(则停止计算,其仅当)来临才消失。故优先及中加入了‘(’将其优先级设为最低
while(!sop.isEmpty()&&map.get(s.charAt(index))<=map.get(sop.peek())){
int num = compute(snum.pop(),snum.pop(),sop.pop());
snum.push(num);
}
//计算完成再将字符入栈
sop.push(s.charAt(index));
}
index++;
}
}
if(!sop.isEmpty()){
int num = compute(snum.pop(),snum.pop(),sop.pop());
snum.push(num);
}
return snum.pop();
}
private int compute(int num1, int num2,char op){
switch(op){
case'-':return num2-num1;
case'+':return num1+num2;
case'*':return num1*num2;
default:return Integer.MIN_VALUE;
}
}
}
(41)NC97 字符串出现次数的TopK问题
前k个最大或最小就想到用堆排序
1、这里有几个重点,语法需要注意
//Map的遍历,对实体,key,value的分别遍历
for(Map.Entry m : map.entrySet())
若key map.keySet()
若value map.valueSet()
2、如何对Map实体构建排序比较器Map.Entry
Comparator> com = new Comparator>(){
public int compare(Map.Entry o1,Map.Entry o2){
if(o1.getValue().equals(o2.getValue())){
return o2.getKey().compareTo(o1.getKey());
}
else{
return o1.getValue()-o2.getValue();
}
}
};
完成代码
public class Solution {
/**
* return topK string
* @param strings string字符串一维数组 strings
* @param k int整型 the k
* @return string字符串二维数组
*/
public String[][] topKstrings (String[] strings, int k) {
// write code here
String[][] res = new String[k][2];
if(k==0)
return new String[][]{};
//加入Map中,不断更新key
Map map = new HashMap();
for(int i = 0;i> com = new Comparator>(){
//值不同,值小的放前面;值同字典大的放前面
public int compare(Map.Entry o1,Map.Entry o2){
if(o1.getValue().equals(o2.getValue())){
return o2.getKey().compareTo(o1.getKey());
}
else{
return o1.getValue()-o2.getValue();
}
}
};
//构建顶堆
Queue> queue = new PriorityQueue>(com);
for(Map.Entry m : map.entrySet()){
if(queue.size()=0;i--){
Map.Entry m = queue.poll();
res[i][0]=m.getKey();
res[i][1]=m.getValue().toString();
}
return res;
}
}
(42)NC112 进制转换
char s = '' 错误写法不能为空字符
int转String :Integer.toString(num)
正弦转char注意要强制类型转换char ch =(char) ('A'+num-10)