进展转换问题
StringBuffer str = new StringBuffer(); // Java中StringBuffer带reverse()
// C++中有这个reverse函数,不过要引#include包
for(num > 0){
str += (num - 1) % 26 + "A";
num = (num - 1) / 26;
}
str.reverse();
输入两个无环的单向链表,找出它们的第一个公共结点,如果没有公共节点则返回空。
判断给定的链表中是否有环。如果有环则返回true,否则返回false
快慢指针法:fast和slow从同一点开始,fast每次走两个,slow每次走一个,相遇就代表有环
fast != null && fast.next != null
创建Set判断长度是否发生变化
拓展:JZ23 链表中环的入口结点
输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针random指向一个随机节点),请对此链表进行深拷贝,并返回拷贝后的头结点。
给定节点数为 n 的二叉树的前序遍历和中序遍历结果,请重建出该二叉树并返回它的头结点。
递归法建树
import java.util.*;
public class Solution {
public TreeNode reConstruct(int [] pre,int [] vin) {
int n = pre.length;
int m = vin.length;
//每个遍历都不能为0
if(n == 0 || m == 0)
return null;
//构建根节点
TreeNode root = new TreeNode(pre[0]);
for(int i = 0; i < vin.length; i++){
//找到中序遍历中的前序第一个元素
if(pre[0] == vin[i]){
//构建左子树
root.left = reConstruct(Arrays.copyOfRange(pre, 1, i + 1), Arrays.copyOfRange(vin, 0, i));
//构建右子树
root.right = reConstruct(Arrays.copyOfRange(pre, i + 1, pre.length), Arrays.copyOfRange(vin, i + 1, vin.length));
break;
}
}
return root;
}
}
Collection
类可以相互转换,类似list.add(new ArrayList(linkedList))
,所以使用LinkedList
代替栈)给定一个二叉树其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包含左右子结点,同时包含指向父结点的next指针
min(p,q)<=val&&val>=max(p,q)
的节点就行了给定一个长度为 n 的数组 nums 和滑动窗口的大小 size ,找出所有滑动窗口里数值的最大值。
如果输入数组{2,3,4,2,6,2,5,1}及滑动窗口的大小3,那么一共存在6个滑动窗口,他们的最大值分别为{4,4,6,6,6,5}; 针对数组{2,3,4,2,6,2,5,1}的滑动窗口有以下6个: {[2,3,4],2,6,2,5,1}, {2,[3,4,2],6,2,5,1}, {2,3,[4,2,6],2,5,1}, {2,3,4,[2,6,2],5,1}, {2,3,4,2,[6,2,5],1}, {2,3,4,2,6,[2,5,1]}。
要求:空间复杂度 O(n),时间复杂度 O(n)
在一个二维数组array中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
给定一个长度为 n 的非降序数组和一个非负数整数 k ,要求统计 k 在数组中出现的次数
要求:空间复杂度 O(1),时间复杂度 O(logn)
// 二分查找
public int bin(int [] array , double k){
int low = 0;
int high = array.length -1;
while(low <= high){
int mid = (high + low) / 2 ;
if(array[mid] > k){
high = mid - 1;
}else if(array[mid] < k){
low = mid + 1;
}else return mid;
}
return low;
}
有一个长度为 n 的非降序数组,比如[1,2,3,4,5],将它进行旋转,即把一个数组最开始的若干个元素搬到数组的末尾,变成一个旋转数组,比如变成了[3,4,5,1,2],或者[4,5,1,2,3]这样的。请问,给定这样一个旋转数组,求数组中的最小值。
空间复杂度:O*(1) ,时间复杂度:O(logn)*
输入一个长度为 n 字符串,打印出该字符串中字符的所有排列,你可以以任意顺序返回这个字符串数组。
例如输入字符串ABC,则输出由字符A,B,C所能排列出来的所有字符串ABC,ACB,BAC,BCA,CBA和CAB。
数字以 0123456789101112131415… 的格式作为一个字符序列,在这个序列中第 2 位(从下标 0 开始计算)是 2 ,第 10 位是 1 ,第 13 位是 1 ,以此类题,请你输出第 n 位对应的数字。
数据范围: 0 < n < 10^9
输入一个长度为n的整型数组array,数组中的一个或连续多个整数组成一个子数组,子数组最小长度为1。求所有子数组的和的最大值。
max(dp[i-1]+array[i],array[i])
输入一个长度为n的整型数组array,数组中的一个或连续多个整数组成一个子数组,找到一个具有最大和的连续子数组。
begin,end
用来保存最大最长的位置,begin_,end_
用来保存每次的新数组Arrays.copyOfRange(array,begin,end+1)
来截断数组一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶(n为正整数)总共有多少种跳法。
假设你有一个数组prices,长度为n,其中prices[i]是股票在第i天的价格,请根据这个价格数组,返回买卖股票能获得的最大收益
1.你可以买入一次股票和卖出一次股票,并非每天都可以买入或卖出一次,总共只能买入和卖出一次,且买入必须在卖出的前面的某一天
2.如果不能获取到任何利润,请返回0
3.假设买入卖出均无手续费
在一个m×n的棋盘的每一格都放有一个礼物,每个礼物都有一定的价值(价值大于 0)。你可以从棋盘的左上角开始拿格子里的礼物,并每次向右或者向下移动一格、直到到达棋盘的右下角。给定一个棋盘及其上面的礼物的价值,请计算你最多能拿到多少价值的礼物?
如输入这样的一个二维数组,
[[1,3,1],
[1,5,1],
[4,2,1]]那么路径 1→3→5→2→1 可以拿到最多价值的礼物,价值为12
max(grid[i][j]+up,grid[i][j]+left)
,返回max请从字符串中找出一个最长的不包含重复字符的子字符串,计算该最长子字符串的长度。
有一种将字母编码成数字的方式:‘a’->1, ‘b->2’, … , ‘z->26’。
我们把一个字符串编码成一串数字,再考虑逆向编译成字符串。
由于没有分隔符,数字编码成字母可能有多种编译结果,例如 11 既可以看做是两个 ‘a’ 也可以看做是一个 ‘k’ 。但 10 只可能是 ‘j’ ,因为 0 不能编译成任何结果。
现在给一串数字,返回有多少种可能的译码结果
dp[i]=dp[i-1] + dp[i-2]
(等于前i-1个组合+第i个 和 前i-2个组合+第i-1与i-2个)dp[i]=dp[i-1] + 1
dp[i]=dp[i-1]
;当大于26时没有意义,返回0dp[i]=dp[i-1]
请设计一个函数,用来判断在一个n乘m的矩阵中是否存在一条包含某长度为len的字符串所有字符的路径。路径可以从矩阵中的任意一个格子开始,每一步可以在矩阵中向左,向右,向上,向下移动一个格子。如果一条路径经过了矩阵中的某一个格子,则该路径不能再进入该格子。 例如
a b c e
s f c s
a d e e
矩阵中包含一条字符串"bcced"的路径,但是矩阵中不包含"abcb"路径,因为字符串的第一个字符b占据了矩阵中的第一行第二个格子之后,路径不能再次进入该格子。
数据范围:0≤n,m≤20 ,1≤len≤25
注意各种排序算法的时间复杂度
算法 | 时间复杂度 | 最好 | 最坏 | 稳定性 | 空间 |
---|---|---|---|---|---|
插入排序 | O(n^2) | O(n) | O(n^2) | 稳定 | |
冒泡排序 | O(n^2) | O(n) | O(n^2) | 稳定 | |
归并排序 | O(nlogn) | O(nlogn) | O(nlogn) | 稳定 | O(n) |
堆排序 | O(nlogn) | O(nlogn) | O(nlogn) | 不稳定 | |
快速排序 | O(nlogn) | O(nlogn) | O(n^2) | 不稳定 |
在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数P。并将P对1000000007取模的结果输出。 即输出P mod 1000000007
要求:空间复杂度 O*(n),时间复杂度 O(nlogn)
给定一个长度为 n 的可能有重复值的数组,找出其中不去重的最小的 k 个数。例如数组元素是4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4(任意顺序皆可)。
要求:空间复杂度 O*(*n) ,时间复杂度 O(nlogn)
计算机中存储的都是补码
正数的补码是他本身,负数的补码为反码加1(这里值我们看到的实际的负数,在计算机中其实本身就是存的补码)
~
按位取反,^
异或,&
与,|
或
~x = -x - 1
<<
左移(乘以2), >>
有符号右移(除2,左边补符号), >>>
无符号右移(除2,左边补0)
加减乘除
加法:先通过异或不带进位的加,在通过与的方式添加进位(JZ65 不用加减乘除做加法)
// x + y
while(y>0){ // 是否有进位
int tem = x ^ y; // 不进位的加
y = (x & y) << 1; // y保存进位并左移一位
x = tem; // x保存本次结果
}
减法:将被减数变为负数(被减数变为其相反数,即需要计算机存这个数相反数的补码,按位取反加一)
// x - y
y = (~y) + 1;
add(x,y);
乘法:先转为正数,通过多次加法实现乘法的效果,再通过是否同号决定符号
除法:同上,不停的减去被减数,直到减数小于被减数,记录次数
输入一个整数 n ,输出该数32位二进制表示中1的个数。其中负数用补码表示。
输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下4 X 4矩阵:
[[1,2,3,4], [5,6,7,8], [9,10,11,12], [13,14,15,16]]
则依次打印出数字
[1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10]
数据范围:
0 <= matrix.length <= 100
0 <= matrix[i].length <= 100
方向数组+边界判断
public ArrayList<Integer> printMatrix(int [][] matrix) {
int n = matrix.length;
if(n == 0) return new ArrayList<>();
int m = matrix[0].length;
int[][] dir = {{0,1},{1,0},{0,-1},{-1,0}}; // 右下左上
ArrayList<Integer> ans = new ArrayList<>();
int pos = 0;
int i = 0;
int j = 0;
while(i >= 0 && j>=0 && i < n && j < m && matrix[i][j] != -1 ){
ans.add(matrix[i][j]);
matrix[i][j] = -1;
if( i + dir[pos][0] >= 0 && j+ dir[pos][1]>=0 && i+ dir[pos][0] < n && j+ dir[pos][1] < m && matrix[i+ dir[pos][0]][j+ dir[pos][1]] != -1){
i += dir[pos][0];
j += dir[pos][1];
}else{
pos = (pos + 1) % 4;
i += dir[pos][0];
j += dir[pos][1];
}
}
return ans;
}
给一个长度为 n 的数组,数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。
例如输入一个长度为9的数组[1,2,3,2,2,2,5,4,2]。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。
数据范围:n≤50000,数组中元素的值 100000≤val≤10000
要求:空间复杂度:O*(1),时间复杂度O(*n)
public int MoreThanHalfNum_Solution(int [] array) {
Arrays.sort(array);
int ans = array[0];
int count = 1;
for(int i = 1;i<array.length;i++){
if(array[i] == array[i-1]){
count++;
if(array.length / 2 < count){
ans = array[i];
}
}else{
count = 1;
}
}
return ans;
}
public int MoreThanHalfNum_Solution(int [] array) {
int cond = array[0];
int num = 1;
for(int i = 1;i<array.length;i++){
if(num == 0){
cond = array[i];
num = 1;
}else if(array[i]!=cond){
num--;
}else{
num++;
}
}
return cond;
}
实现函数 double Power(double base, int exponent),求base的exponent次方。
注意:
1.保证base和exponent不同时为0。
2.不得使用库函数,同时不需要考虑大数问题
3.有特殊判题,不用考虑小数点后面0的位数。
数据范围: ∣base∣≤100 ,∣exponent∣≤100 ,保证最终结果一定满足 ∣val∣≤104
空间复杂度 O(1),时间复杂度 O(n)
public double Power(double base, int exponent) {
if(exponent == 0) return 1;
if(exponent < 0) {
base = 1. / base;
exponent = - exponent;
}
if(exponent % 2 == 0){
return Power(base , exponent / 2) * Power(base , exponent / 2);
}else{
return Power(base , exponent / 2) * Power(base , exponent / 2) * base;
}
}
可能会更新