文章目录
- 【一】常见的api使用
- 【二】全排序
- 【三】青蛙跳
- 【四】经典问题:对于一个m*n的网格,从左上角的方格到右下角的方格,共有多少条路径(递归)
- 【五】经典问题:对于一个m*n的网格,从左上角的方格到右下角的方格的最小路径(动态规划)
- 【六】在反向波兰表示法中计算算术表达式的值。有效的运算符是+, - ,*,/。每个操作数可以是整数或另一个表达式
- 【七】给定字符串s和单词字典dict,确定s是否可以被分割成一个或多个字典单词的空格分隔序列。
- 【八】给定一个只包含字符'(',')','{','}','['和']'的字符串,确定输入字符串是否有效。
- 【九】给定未排序的整数数组,找到最长连续元素序列的长度。
- 【十】给定mxn元素矩阵(m行,n列),以螺旋顺序返回矩阵的所有元素。
- 【十一】给定一个链表,确定它是否有一个循环,如果我们有2个指针 - 快速和慢速。如果存在圆圈,则保证快速的一个将遇到慢速的一个。
- 【十二】输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树
【一】常见的api使用
toCharArray() //get char array of a String
Arrays.sort() //sort an array
Arrays.toString(char[] a) //convert to string
charAt(int x) //get a char at the specific index
length() //string length
length //array size
substring(int beginIndex)
substring(int beginIndex, int endIndex)
Integer.valueOf()//string to integer
String.valueOf()/integer to string
PriorityQueue插入保持内部有序:
PriorityQueue<Integer> heap = new PriorityQueue<>();
字符进行大小写转换:
Character.toUpperCase(c)
Character.toLowerCase(c);
常见api进行10,2,8,16进制的转换:
//十进制转二进制
System.out.println(Integer.toBinaryString(10));
//十进制转八进制
System.out.println(Integer.toOctalString(10));
//十进制转十六进制
System.out.println(Integer.toHexString(10));
// 其他进制转换为十进制
Integer.parseInt(String s ,int radix)
【二】全排序
public class Main {
public static void main(String args[]) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
int[] array = new int[n];
for (int i = 0; i < array.length; i++) {
array[i] = scanner.nextInt();
}
List<Integer[]> list = new ArrayList<>();
getData(list,0,n,array);
System.out.println(list.toString());
}
private static void getData(List<Integer[]> list,int start, int end, int[] array) {
if(start>=end){
Integer[] item = new Integer[array.length];
for (int i = 0; i < array.length; i++) {
item[i] = array[i];
}
list.add(item);
}
for (int i = start; i < end; i++) {
swap(i,start,array);
getData(list,start+1,end,array);
swap(i,start,array);
}
}
private static void swap(int i, int j, int[] array) {
int tem = array[i];
array[i] = array[j];
array[j] = tem;
}
}
【三】青蛙跳
一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法(先后次序不同算不同的结果)。
public class Solution {
public int JumpFloor(int target) {
int count = getcount(0,target);
return count;
}
public int getcount(int current,int target){
//表示当前台阶数大于总台阶数,很显然这种情况不符合,走不通,记为 0
if (current > target) {
return 0;
}
//表示当前台阶数正好等于总的台阶数,那么这种情况符合,记为 1
if (current == target) {
return 1;
}
return getcount(current + 1, target) + getcount(current + 2, target);
}
}
注意这中解法不是很适合数据比较大的,数据大导致递归深度很大,以下提供非递归的方法:
dp(i) = dp(i-2) + dp(i-1)
public class Solution {
public int JumpFloor(int target) {
if(target <= 2){
return target;
}
int pre2 = 1, pre1 = 2;
for (int i = 3; i <= target; i++){
int cur = pre2 + pre1;
pre2 = pre1;
pre1 = cur;
}
return pre1;
}
}
【四】经典问题:对于一个m*n的网格,从左上角的方格到右下角的方格,共有多少条路径(递归)
int sum(int m, int n)//递归
{
if (m == 1 || n == 1)
return 1;
int total = sum(m - 1, n) + sum(m, n - 1);
return total;
}
【五】经典问题:对于一个m*n的网格,从左上角的方格到右下角的方格的最小路径(动态规划)
public static int getMin(int[][] map, int n, int m) {
//特殊输入
if(map==null||n<=0||m<=0) return 0;
//①创建动态规划结果矩阵dp[][]
int[][] dp=new int[n][m];
//②求解第1行第1列的结果值
dp[0][0]=map[0][0];
for(int i=1;i<m;i++){
dp[0][i]=dp[0][i-1]+map[0][i];
}
//求第1列的结果值
for(int i=1;i<n;i++){
dp[i][0]=dp[i-1][0]+map[i][0];
}
//③从上到下,从左到右求任意dp[i][j]
for(int i=1;i<n;i++){
for(int j=1;j<m;j++){
dp[i][j]=map[i][j]+Math.min(dp[i-1][j],dp[i][j-1]);
}
}
//④返回右下角的结果值
return dp[n-1][m-1];
}
【六】在反向波兰表示法中计算算术表达式的值。有效的运算符是+, - ,*,/。每个操作数可以是整数或另一个表达式
public static int getAns(String[] tokens){
int returnValue = 0;
String operators = "+-*/";
Stack<String> stack = new Stack<String>();
for (String t:tokens){
if(!operators.contains(t)){
stack.push(t);
}
else{
int a = Integer.parseInt(stack.pop());
int b = Integer.parseInt(stack.pop());
switch (t){
case "+":
stack.push(String.valueOf(a+b));
break;
case "-":
stack.push(String.valueOf(a-b));
break;
case "*":
stack.push(String.valueOf(a*b));
break;
case "/":
stack.push(String.valueOf(a/b));
break;
}
}
}
returnValue+=Integer.parseInt(stack.pop());
return returnValue;
}
【七】给定字符串s和单词字典dict,确定s是否可以被分割成一个或多个字典单词的空格分隔序列。
例如,给定
s =“leetcode”,
dict = [“leet”,“code”]。
返回true,因为“leetcode”可以被分段为“leet code”
public static boolean wordBreak(String s, Set<String> wordDict) {
int[] pos = new int[s.length()+1];
Arrays.fill(pos, -1);
pos[0]=0;
for(int i=0; i<s.length(); i++){
if(pos[i]!=-1){
for(int j=i+1; j<=s.length(); j++){
String sub = s.substring(i, j);
if(wordDict.contains(sub)){
pos[j]=i;
}
}
}
}
return pos[s.length()]!=-1;
}
【八】给定一个只包含字符’(’,’)’,’{’,’}’,’[‘和’]'的字符串,确定输入字符串是否有效。
public static boolean isValid(String s) {
HashMap<Character, Character> map = new HashMap<Character, Character>();
map.put('(', ')');
map.put('[', ']');
map.put('{', '}');
Stack<Character> stack = new Stack<Character>();
for (int i = 0; i < s.length(); i++) {
char curr = s.charAt(i);
if (map.keySet().contains(curr)) {
stack.push(curr);
} else if (map.values().contains(curr)) {
if (!stack.empty() && map.get(stack.peek()) == curr) {
stack.pop();
} else {
return false;
}
}
}
return stack.empty();
}
【九】给定未排序的整数数组,找到最长连续元素序列的长度。
例如,给定[100, 4, 200, 1, 3, 2],最长的连续元素序列应该是[1, 2, 3, 4]。它的长度是4
public int longestConsecutive(int[] nums) {
HashSet<Integer> set = new HashSet<>();
for(int num: nums) set.add(num);
int result = 0;
for(int num: nums){
int count = 1;
int down = num-1;
while(set.contains(down)){
set.remove(down);
down--;
count++;
}
int up = num+1;
while(set.contains(up)){
set.remove(up);
up++;
count++;
}
result = Math.max(result, count);
}
return result;
}
【十】给定mxn元素矩阵(m行,n列),以螺旋顺序返回矩阵的所有元素。
public static List<Integer> getMria(int[][]array){
List<Integer> list = new ArrayList<>();
int left = 0;
int right=array[0].length-1;
int top = 0;
int bottom = array.length-1;
while (list.size()<((right+1)*(bottom+1))){
for (int i = left; i <= right; i++) {
list.add(array[top][i]);
}
top++;
for (int i = top; i <=bottom ; i++) {
list.add(array[i][right]);
}
right--;
if(top>bottom)
break;
for (int i = right; i >=left ; i--) {
list.add(array[bottom][i]);
}
bottom--;
if(left>right)
break;
for (int i = bottom; i >=top; i--) {
list.add(array[i][left]);
}
}
return list;
}
【十一】给定一个链表,确定它是否有一个循环,如果我们有2个指针 - 快速和慢速。如果存在圆圈,则保证快速的一个将遇到慢速的一个。
public static boolean hasCycle(ListNode head) {
ListNode fast = head;
ListNode slow = head;
while (fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
if (slow == fast)
return true;
}
return false;
}
【十二】输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树
/**
* Definition for binary tree
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
public class Solution {
public TreeNode reConstructBinaryTree(int [] pre,int [] in) {
//由于重建二叉树的过程会用到很多边界值,所以题目所给的方法的参数是不够用的
//所以,在下面重载了这个方法,每次传入前序和中序序列以及起始位置
TreeNode root=reConstructBinaryTree(pre,0,pre.length-1,in,0,in.length-1);
return root;
}
private TreeNode reConstructBinaryTree(int [] pre,int startPre,int endPre,int [] in,int startIn,int endIn) {
//这里是判断结束的标志,由于是递归算法,我们不可能一直执行下去,所以需要结束标志
//下面这两种情况发生一个就会结束
if(startPre>endPre||startIn>endIn)
{
return null;
}
//首先找到根节点
TreeNode root=new TreeNode(pre[startPre]);
//对中序遍历进行查找根节点
for(int i=startIn;i<=endIn;i++)
{
//找到之后,分别对左子树和右子树进行递归算法,重复此步骤
if(in[i]==pre[startPre])
{
//重建二叉树的关键就是找到其中的边界值,边界值在图中已经做了描述
root.left=reConstructBinaryTree(pre,startPre+1,startPre+i-startIn,in,startIn,i-1);
root.right=reConstructBinaryTree(pre,startPre+i-startIn+1,endPre,in,i+1,endIn);
break;
}
}
return root;
}
}