文章目录
- 3、数组中重复的数字
- 4、二位数组中的查找
- 5、替换空格
- 6、从尾到头打印链表
- 7、重建二叉树
- 8、二叉树的下一个节点
- 9、用两个栈实现队列
- 10、斐波那契数列
- 11、旋转数组中的最小数字
- 12、矩阵中的路径
- 13、机器人的运动范围
- 14、剪绳子
- 15、二进制中1的个数
- 16、数值的整数次方
- 17、打印从1到最大的n位数
- 18、删除链表节点
- 19、正则表达式匹配
- 20、表示数值的字符串
- 21、调整数组顺序使奇数位于偶数前面
- 22、链表中倒数第K个节点
- 23、链表中环的入口点
- 24、反转链表
- 25、合并两个排序链表
- 26、树的子结构
- 27、二叉树镜像
- 28、对称二叉树
- 29、顺时针打印矩阵
- 30、包含min函数的栈
- 31、栈的压入弹出序列
- 32、从上到下打印二叉树
- 33、二叉搜索树的后序遍历序列
- 34、二叉树中和为某一值的路径
- 35、复杂链表的赋值
- 36、二叉搜索树与双向列表
- 37、序列化二叉树
- 38、字符串的排列
- 39、数组中出现次数超过一半的数字
- 40、最小的K个数
- 41、数据流中的中位数
- 42、连续子数组的最大和
- 43、1~n中1出现的次数
- 44、数字序列中某一位的数字
- 45、把数组排成最小的数
- 46、把数字翻译成字符串
- 47、礼物的最大价值
- 48、最长不含重读字符的子字符串
- 49、丑数
- 50、第一个只出现一次的字符
- 51、数组中的逆序对
- 52、两个链表的第一个公共节点
- 53、在排序数组中查找数字
- 54、二叉搜索树的第K大节点
- 55、二叉树的深度
- 56、数组中数字出现的次数
- 57、和为s的数字
- 58、反转字符串
- 59、队列的最大值
- 60、n个骰子的点数
- 61、扑克牌中的顺子
- 62、圆圈中最后剩下的数字
- 63、股票的最大利润
- 64、求 1+2+3+。。。+n
- 65、不用加减乘除做加法
- 66、构建乘积数组
- 67、把字符串转换成整数
3、数组中重复的数字
public static boolean duplicate(int numbers[],int length,int [] duplication) {
duplication[0] = -1;
if(length <=0 || numbers == null) {
return false;
}
for (int i=0; i<numbers.length; i++) {
if (numbers[i] != i) {
if (numbers[i] == numbers[numbers[i]]){
duplication[0] = numbers[i];
return true;
}
int temp = numbers[numbers[i]];
numbers[numbers[i]] = numbers[i];
numbers[i] = temp;
}
}
return false;
}
4、二位数组中的查找
public boolean Find(int target, int [][] array) {
if (array.length <= 0 || array[0].length <= 0) {
return false;
}
int row = array.length;
int col = array[0].length;
int r = 0;
int c = col-1;
//注意边界的控制
while(r <= row-1 && c >= 0){
if (target == array[r][c]) {
return true;
}
else if (target > array[r][c]) {
r++;
}else {
c--;
}
}
return false;
}
5、替换空格
public static String replaceSpace(StringBuffer str) {
int p1 = str.length() - 1;
for (int i=0, len=str.length(); i<len; i++) {
if (str.charAt(i) == ' ') {
str.append(" ");
}
}
int p2 = str.length() - 1;
while (p1 >= 0 && p2 > p1) {
if (str.charAt(p1) != ' ') {
str.setCharAt(p2--, str.charAt(p1--));
} else {
str.setCharAt(p2--,'0');
str.setCharAt(p2--,'2');
str.setCharAt(p2--,'%');
}
}
return str.toString();
}
6、从尾到头打印链表
public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
ArrayList<Integer> ret = new ArrayList<>();
if (listNode != null) {
ret.addAll(printListFromTailToHead(listNode.next));
ret.add(listNode.val);
}
return ret;
}
7、重建二叉树
private Map<Integer, Integer> indexForInOrders = new HashMap<>();
public TreeNode reConstructBinaryTree(int [] pre,int [] in) {
for (int i=0; i<in.length; i++) {
//键为中序遍历 值是该值的下标
indexForInOrders.put(in[i],i);
}
return reBuildTre(pre,0,pre.length-1,0);
}
private TreeNode reBuildTre(int[] pre, int preL, int preR, int inL) {
if (preL > preR) {
return null;
}
TreeNode root = new TreeNode(pre[preL]);
int inIndex = indexForInOrders.get(root.val);
//计算左子树大小 开始时候 找到根节点的位置 减去0 0-root 是根的左子树
int leftTreeSize = inIndex - inL;
//preL是根
root.left = reBuildTre(pre, preL+1, preL+leftTreeSize, inL);
root.right = reBuildTre(pre,preL+leftTreeSize+1,preR,inL+leftTreeSize+1);
return root;
}
8、二叉树的下一个节点
public TreeLinkNode GetNext(TreeLinkNode pNode) {
if (pNode.right != null) {
//该节点有右节点 那么右节点的最左节点就是
TreeLinkNode node = pNode.right;
while (node.left != null) {
node = node.left;
}
return node;
} else {
//该节点没有右节点 那么它是它父节点的左节点吗 是 父节点就是下一个节点
// 否 用父节点代替当前节点 重复前面的判断
while (pNode.next != null) {
TreeLinkNode parent = pNode.next;
if (parent.left == pNode) {
return parent;
}
pNode = pNode.next;
}
}
return null;
}
9、用两个栈实现队列
Stack<Integer> stack1 = new Stack<Integer>();
Stack<Integer> stack2 = new Stack<Integer>();
public void push(int node) {
stack1.push(node);
}
public int pop() {
if(stack2.isEmpty()) {
while (!stack1.empty()) {
stack2.push(stack1.pop());
}
}
int temp = stack2.pop();
while (!stack2.empty()) {
stack1.push(stack2.pop());
}
return temp;
}
10、斐波那契数列
public int Fibonacci(int n) {
if(n == 0) {
return 0;
} else if(n == 2 || n == 1) {
return 1;
} else {
return Fibonacci(n-1) + Fibonacci(n-2);
}
}
11、旋转数组中的最小数字
public int minNumberInRotateArray(int [] array) {
if(array.length == 0 || array == null) {
return 0;
}
int l = 0;
int h= array.length-1;
while(l < h) {
int m =l + (h - l)/2;
if (array[m] <= array[h]){
//说明不在这个范围 m-h 但是可能在 l-h
//45124 l=0 h=4 m=2
h = m;
}else {
//array[m] > array[h]
//567123 必定在 m+1 ~ h 中
l = m+1;
}
}
return array[l];
}
12、矩阵中的路径
public boolean hasPath(char[] array, int rows, int cols, char[] str) {
if (rows == 0 || cols == 0) {
return false;
}
boolean[][] marked = new boolean[rows][cols];
char[][] matrix = buildMatrix(array, rows, cols);
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
//如果backtracking返回ture 那么存在 否则继续试探下一个
if (backtracking(matrix, str, rows, cols, marked, 0, i, j)) {
return true;
}
}
}
//全部找完,backtracking没找到 不存在
return false;
}
private boolean backtracking(char[][] matrix, char[] str, int rows, int cols,
boolean[][] marked, int pathLen, int r, int c) {
if (pathLen == str.length) {
return true;
}
if (r < 0 || r >= rows || c < 0 || c >= cols
|| matrix[r][c] != str[pathLen] || marked[r][c]) {
//matrix[r][c] != str[pathLen] 该字符与要找的不一样
//marked[r][c] 已经标记过来了 不能重复
return false;
}
//找到了某个字符
marked[r][c] = true;
//遍历它的上下左右
if (backtracking(matrix, str, rows, cols, marked, pathLen+1, r+1, c )
|| backtracking(matrix, str, rows, cols, marked, pathLen+1, r-1, c)
|| backtracking(matrix, str, rows, cols, marked, pathLen+1, r, c-1)
|| backtracking(matrix, str, rows, cols, marked, pathLen+1, r, c+1)) {
return true;
}
//它的上下左右没有路径,那么找到的单个字符没有用,置为false
marked[r][c] = false;
return false;
}
private char[][] buildMatrix(char[] array, int rows, int cols) {
char[][] matrix = new char[rows][cols];
for (int r = 0, idx = 0; r < rows; r++) {
for (int c = 0; c < cols; c++) {
matrix[r][c] = array[idx++];
}
}
return matrix;
}
13、机器人的运动范围
递归
public int movingCount(int threshold, int rows, int cols){
boolean[][] flag = new boolean[rows][cols];
return calculate(threshold, rows, cols, 0, 0, flag);
}
private static int calculate(int threshold, int rows, int cols,
int i, int j, boolean[][] flag) {
if (i >= rows || i < 0 || j >= cols || j < 0 || flag[i][j]) {
return 0;
}
if (i/10 + i%10 + j/10 + j%10 <= threshold) {
flag[i][j] = true;
return calculate(threshold, rows, cols, i - 1, j, flag)
+ calculate(threshold, rows, cols, i + 1, j, flag)
+ calculate(threshold, rows, cols, i, j - 1, flag)
+ calculate(threshold, rows, cols, i, j + 1, flag)
+ 1;
} else {
return 0;
}
}
14、剪绳子
public static int max(int n) {
//小于2的时候 不能再剪了
if (n < 2) {
return 0;
}
//n等于2的时候 分成1的两段
if (n == 2) {
return 1;
}
//n等于3的时候 分成 1和2的两段
if (n == 3) {
return 2;
}
//大于3的时候 尽可能分成长度为3的段
int t3 = n / 3;
//此时最后应该剩余4 分成 2*2的两段 而不是 1和3
if ((n - t3 * 3) == 1) {
t3 -= 1;
}
int t2 = (n - t3 * 3) / 2;
return (int) Math.pow(3,t3) * (int) Math.pow(2,t2);
}
15、二进制中1的个数
public int NumberOf1(int n) {
// 7 0111
// 6 0110
// 5 0101
//一个数 减去1 如果最低位是1 那么这位变为0 7->6
// 如果最低位是0 找到高位第一个1 变为0 后面变为1 6->5
//那么 n & n-1 就会把最右边的1变为0
int count = 0;
while(n != 0) {
count++;
n = n & (n-1);
}
return count;
}
16、数值的整数次方
public double Power(double base, int exponent) {
if (exponent == 0) {
return 1;
}
if (exponent == 1) {
return base;
}
//用来标记exponent是正数还是负数
boolean flag = false;
if (exponent < 0) {
flag = true;
exponent = -exponent;
}
double pow = Power(base * base, exponent / 2);
if (exponent % 2 == 1) {
//奇数次幂要多乘一个
pow *= base;
}
return flag ? 1/pow : pow;
}
17、打印从1到最大的n位数
private static void printMaxNumOfN(int n) {
if (n <= 0) {
return;
}
char[] num = new char[n];
printMaxNumOfN(num, 0);
}
private static void printMaxNumOfN(char[] num, int len) {
if (len == num.length) {
printNum(num);
return;
}
for (int i=0; i<10; i++) {
num[len] = (char) (i + '0');
printMaxNumOfN(num, len + 1);
}
}
/**
* 打印数字 过滤0
* @param num
*/
private static void printNum(char[] num) {
int index = 0;
while (index < num.length && num[index] == '0') {
index++;
}
while (index < num.length) {
System.out.print(num[index++]);
}
System.out.println();
}
18、删除链表节点
/**
* 在O(1)时间内删除一个节点
* @param head 头结点
* @param deleteNode 要删除的节点
* @return
*/
public ListNode deleteNode(ListNode head, ListNode deleteNode) {
if (head == null || deleteNode == null) {
return null;
}
if (deleteNode.next != null) {
// 要删除的节点不是尾节点
ListNode next = deleteNode.next;
deleteNode.val = next.val;
deleteNode.next = next.next;
} else {
if (head == deleteNode) {
// 只有一个节点
head = null;
}
else {
ListNode cur = head;
while (cur.next != deleteNode) {
cur = cur.next;
}
cur.next = null;
}
}
return head;
}
/**
* 删除链表中的重复节点
* TODO
* @param pHead
* @return
*/
public ListNode deleteDuplication(ListNode pHead) {
if (pHead == null || pHead.next == null) {
return pHead;
}
ListNode next = pHead.next;
//头节点是重复值 找到最后一个重复值 删除
if (pHead.val == next.val) {
while (next != null && pHead.val == next.val) {
next = next.next;
}
return deleteDuplication(next);
} else {
//头节点不是重复值 递归后面的节点
pHead.next = deleteDuplication(pHead.next);
return pHead;
}
}
19、正则表达式匹配
public static boolean match(char[] str, char[] pattern) {
if(str == null || pattern == null){
return false;
}
return match(str, 0, pattern, 0);
}
private static boolean match(char[] str, int i, char[] pattern, int j){
//特别注意这里:一定是判断pattern是否遍历完了
if(pattern.length == j){
return str.length == i;
}
//如果遇到*就是很特殊的情况了
if(j < pattern.length - 1 && pattern[j+1] == '*'){
// str --> a pat --> .* pattern[j] == '.'
if(i < str.length && (str[i] == pattern[j] || pattern[j] == '.')){
//匹配上了,有两条路可以往后走
// str --> aa pat --> a* str[i] == pattern[j]
// 有多个一样 str --> aaa pat --> a*a i在第一个a
return match(str, i+1, pattern, j)
// 但是上面的不能处理 "aaa","a*a" 这样串里的a一直用完了 会留下模式串的a
|| match(str, i, pattern, j+2);
// . 匹配任意字符 所以 str[i] == pattern[j] 和 pattern[j] == '.'等价
} else{
// str --> a pat --> b*
// 没匹配上,那个*就代表其前面的字母使用0次,从j+2开始寻找a
return match(str, i, pattern, j+2);
}
}
//没遇到*就是最简单的了。
if(i < str.length && (str[i] == pattern[j] || pattern[j] == '.')){
return match(str, i+1, pattern, j+1);
}
return false;
}
20、表示数值的字符串
//"-.123"
/**
* [] 字符集合
* () 分组
* ? 重复0~1次
* + 重复1~n次
* * 重复0~n次
* . 任意
* \\. 转义后的.
* \\d 数字
* @param str
* @return
*/
public boolean isNumeric(char[] str) {
if (null == str || str.length == 0) {
return false;
}
// [+-]? +-号 出现0或者1次
// d* 正负号之后 可能出现数字 0或者多 +100 +.
// // (\\.\\d+)? 出现. .后面必须有数字数字
//"1+23" false
// ([eE][+-]?\d+)* 必须出现e和E 后面才可能出现+- +-后必须出现数字 -1E-16
return new String(str).matches("[+-]?\\d*(\\.\\d+)?([eE][+-]?\\d+)*");
}
21、调整数组顺序使奇数位于偶数前面
public int[] reOrderArray(int [] array) {
int[] arr = array.clone();
int j = 0;
int o = 0;
for (int i=0; i<array.length; i++) {
//记录奇数的个数
if (array[i] % 2 != 0) {
j++;
}
}
o = j;
j = 0;
for(int k=0; k<arr.length; k++) {
if (arr[k] % 2 == 0){
array[o++] = arr[k];
}else {
array[j++] = arr[k];
}
}
return array;
}
22、链表中倒数第K个节点
public ListNode FindKthToTail(ListNode head,int k) {
if (head == null) {
return null;
}
ListNode p = head;
ListNode q = head;
while (p != null && k-- > 0) {
p = p.next;
}
//k大于长度 溢出
if (k > 0) {
return null;
}
//不能这样 如果K大于链表长度 就会溢出
// for (int i=0; i<k; i++) {
// p = p.next;
// }
while (null != p) {
p = p.next;
q = q.next;
}
return q;
}
23、链表中环的入口点
public ListNode EntryNodeOfLoop(ListNode pHead){
ListNode p1 = pHead;
ListNode p2 = pHead;
boolean flag = false;
while(p1 != null && p2.next != null) {
p1 = p1.next;
p2 = p2.next.next;
if(p1 == p2) {
flag = true;
p1 = pHead;
while(p1 != p2) {
p1 = p1.next;
p2 = p2.next;
}
return p1;
}
}
if(!flag) {
return null;
}
return null;
}
24、反转链表
public ListNode ReverseList(ListNode head) {
ListNode newHead = new ListNode(-1);
while (null != head) {
ListNode node = head.next;
head.next = newHead.next;
newHead.next = head;
head = node;
}
return newHead.next;
}
25、合并两个排序链表
public ListNode Merge(ListNode list1,ListNode list2) {
if (list1 == null && list2 == null) {
return null;
}
if (list1 == null || list2 == null){
return list1 == null ? list2 : list1;
}
ListNode mergeList = new ListNode(-1);
ListNode cur = mergeList;
while (list1 != null && list2 != null) {
if (list1.val < list2.val) {
cur.next = list1;
list1 = list1.next;
}else {
cur.next = list2;
list2 = list2.next;
}
cur = cur.next;
}
if (list1 != null) {
cur.next = list1;
}
if (list2 != null) {
cur.next = list2;
}
return mergeList.next;
}
26、树的子结构
public boolean HasSubtree(TreeNode root1,TreeNode root2) {
if(root1 == null || null == root2) {
return false;
}
return isSubTree(root1, root2)
|| HasSubtree(root1.left, root2)
|| HasSubtree(root1.right, root2);
}
private static boolean isSubTree(TreeNode root1, TreeNode root2) {
if (null == root2) {
return true;
}
if(null == root1) {
return false;
}
if(root1.val != root2.val) {
return false;
}
return isSubTree(root1.left, root2.left) && isSubTree(root1.right, root2.right);
}
27、二叉树镜像
public void Mirror(TreeNode root) {
if (root == null) {
return;
}
mirror(root);
Mirror(root.left);
Mirror(root.right);
}
private void mirror(TreeNode root) {
TreeNode temp = root.left;
root.left = root.right;
root.right = temp;
}
28、对称二叉树
boolean isSymmetrical(TreeNode pRoot){
if(pRoot == null) {
return true;
}
return isSymmetrical(pRoot.left, pRoot.right);
}
private boolean isSymmetrical(TreeNode left, TreeNode right) {
if(left == null && right == null) {
return true;
}
if(left == null || right == null) {
return false;
}
if(left.val != right.val) {
return false;
}
return isSymmetrical(left.left,right.right) && isSymmetrical(left.right, right.left);
}
29、顺时针打印矩阵
public ArrayList<Integer> printMatrix(int [][] matrix) {
//顺序打印行
int rs = 0;
//逆序打印行
int rn = matrix.length - 1;
//顺序打印列
int cs = 0;
//逆序打印列
int cn = matrix[0].length - 1;
//标志 原来交换行列
boolean flag = false;
ArrayList<Integer> list = new ArrayList<>();
while (rs <= rn && cs >= cn) {
if (!flag) {
//正向打印行列
for(int i=rs; i<=rn; i++) {
list.add(matrix[rs][i]);
}
rs++;
for (int i=cs; i>=cn; i++) {
list.add(matrix[i][cs]);
}
cs--;
flag = true;
} else {
//逆向打印行列
for (int i=rn; i>=rs; i--) {
list.add(matrix[rn][i]);
}
rn--;
for (int i=cn; i>= cs; i--) {
list.add(matrix[i][cn]);
}
cn++;
flag = false;
}
}
return list;
}
30、包含min函数的栈
private Stack<Integer> dataStack = new Stack<>();
private Stack<Integer> minStack = new Stack<>();
public void push(int node) {
dataStack.push(node);
minStack.push(minStack.isEmpty() ? node : Math.min(minStack.peek(),node));
}
public void pop() {
dataStack.pop();
minStack.pop();
}
public int top() {
return dataStack.peek();
}
public int min() {
return minStack.peek();
}
31、栈的压入弹出序列
public boolean IsPopOrder(int [] pushA,int [] popA) {
int n = pushA.length;
Stack<Integer> stack = new Stack<>();
for (int pushIndex = 0, popIndex = 0; pushIndex < n; pushIndex++) {
stack.push(pushA[pushIndex]);
while (popIndex < n && !stack.isEmpty()
&& stack.peek() == popA[popIndex]) {
stack.pop();
popIndex++;
}
}
return stack.isEmpty();
}
32、从上到下打印二叉树
public ArrayList<Integer> printFromTopToBottom(TreeNode root) {
if (null == root) {
return new ArrayList<>();
}
ArrayList<Integer> list = new ArrayList<>();
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
while (!queue.isEmpty()) {
TreeNode node = queue.poll();
list.add(node.val);
if (null != node.left) {
queue.offer(node.left);
}
if (null != node.right) {
queue.offer(node.right);
}
}
return list;
}
33、二叉搜索树的后序遍历序列
public static void main(String[] args) {
int[] arr1 = {5,7,6,9,11,10,8};
int[] arr2 = {7,4,6,5};
Solution s = new Solution();
System.out.println(s.VerifySquenceOfBST(arr1));
System.out.println(s.VerifySquenceOfBST(arr2));
}
public boolean VerifySquenceOfBST(int [] sequence) {
if (sequence.length == 0 || null == sequence) {
return false;
}
return subTraversal(sequence, 0, sequence.length - 1);
}
private boolean subTraversal(int[] arr, int first, int last) {
if (last - first <= 1) {
return true;
}
int root = arr[last];
int index = first;
while (index < last && arr[index] <= root) {
index++;
}
for (int i=index+1; i<last; i++) {
if (arr[i] < root) {
return false;
}
}
return subTraversal(arr, first, index - 1) && subTraversal(arr, index, last - 1);
}
34、二叉树中和为某一值的路径
ArrayList<ArrayList<Integer>> ret = new ArrayList<>();
public ArrayList<ArrayList<Integer>> FindPath(TreeNode root, int target) {
backtracking(root, target, new ArrayList());
return ret;
}
private void backtracking(TreeNode node, int target, ArrayList list) {
if (null == node) {
return;
}
list.add(node.val);
target -= node.val;
//和为target 并且是叶子节点
if (target == 0 && null == node.right && null == node.left) {
ret.add(new ArrayList<>(list));
} else {
backtracking(node.left, target, list);
backtracking(node.right, target, list);
}
//返回父节点的时候 要删除路径上的当前节点
list.remove(list.size()-1);
}
35、复杂链表的赋值
public RandomListNode Clone(RandomListNode pHead) {
if (pHead == null) {
return null;
}
// 插入新节点
RandomListNode cur = pHead;
while (cur != null) {
RandomListNode clone = new RandomListNode(cur.label);
clone.next = cur.next;
cur.next = clone;
cur = clone.next;
}
// 建立 random 链接
cur = pHead;
while (cur != null) {
RandomListNode clone = cur.next;
if (cur.random != null) {
//看图很直观
clone.random = cur.random.next;
}
cur = clone.next;
}
// 拆分
cur = pHead;
RandomListNode pCloneHead = pHead.next;
while (cur.next != null) {
RandomListNode nextNode = cur.next;
cur.next = nextNode.next;
cur = nextNode;
}
return pCloneHead;
}
36、二叉搜索树与双向列表
public TreeNode Convert(TreeNode pRootOfTree) {
if (null == pRootOfTree) {
return null;
}
TreeNode lastNode = null;
lastNode = baseConvert(pRootOfTree, lastNode);
TreeNode head = lastNode;
while (head.left != null) {
head = head.left;
}
return head;
}
public TreeNode baseConvert(TreeNode root, TreeNode lastNode) {
if (null == root) {
return lastNode;
}
TreeNode cur = root;
if (cur.left != null) {
lastNode = baseConvert(cur.left, lastNode);
}
cur.left = lastNode;
if (lastNode != null) {
lastNode.right = cur;
}
lastNode = cur;
if (cur.right != null) {
lastNode = baseConvert(cur.right, lastNode);
}
return lastNode;
}
37、序列化二叉树
private String serializeStr;
String Serialize(TreeNode root) {
if(null == root) {
return "$";
}
return root.val + "," + Serialize(root.left) + "," + Serialize(root.right);
}
TreeNode Deserialize() {
if(null == serializeStr || serializeStr.length() == 0) {
return null;
}
int index = serializeStr.indexOf(",");
String node = index == -1 ? serializeStr : serializeStr.substring(0, index);
serializeStr = index == -1 ? "" : serializeStr.substring(index + 1);
if (node.equals("$")) {
return null;
} else {
int val = Integer.valueOf(node);
TreeNode t = new TreeNode(val);
t.left = Deserialize();
t.right = Deserialize();
return t;
}
}
TreeNode Deserialize(String str) {
serializeStr = str;
return Deserialize();
}
38、字符串的排列
public static void main(String[] args) {
Solution1 s = new Solution1();
s.Permutation("abc");
}
TreeSet<String> ret = new TreeSet<>();
public ArrayList<String> Permutation(String str) {
if (null == str) {
return new ArrayList<>();
}
return permutation(str.toCharArray(), 0);
}
private ArrayList<String> permutation(char[] chars, int pos) {
//结束条件 长度==总长 是一个正确的排列了
if (pos == chars.length - 1) {
String s = String.valueOf(chars);
ret.add(s);
}
for (int i=pos; i<chars.length; i++) {
//第i个位置的 和后面的所有进行交换
char temp = chars[i];
chars[i] = chars[pos];
chars[pos] = temp;
//第i个位置的 和后面的所有进行交换
permutation(chars, pos+1);
// a bcsdf
// 前面是排列好的那部分 a和其他分别换完之后
// 再回去它自己的正确位置
temp = chars[i];
chars[i] = chars[pos];
chars[pos] = temp;
}
ArrayList<String> list = new ArrayList<>(ret);
return list;
}
39、数组中出现次数超过一半的数字
public static int moreThanHalfNum_Solution(int [] arr) {
if(arr.length == 1) {
return arr[0];
}
int num = arr[0], count = 1;
for (int i=1,len=arr.length; i<len; i++) {
if (num == arr[i]) {
count++;
} else {
count--;
}
if (count == 0) {
num = arr[i];
count = 1;
}
}
//num中保留了可能出现次数最多的数
int cnt = 0;
for (int i : arr) {
if (num == i) {
cnt++;
}
}
return cnt > arr.length / 2 ? num : 0;
}
40、最小的K个数
public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {
int l = 0, h = input.length - 1;
ArrayList<Integer> list = new ArrayList<>();
if(k > input.length) {
return list;
}
while(l < h) {
int p = partition(input, l, h);
if(p < k) {
l = l + 1;
} else if(p > k) {
h = h - 1;
} else {
break;
}
}
for(int i=0; i<k; i++) {
list.add(input[i]);
}
return list;
}
private static int partition(int[] arr, int start, int end) {
int left = start;
int right = end;
int pivot = arr[start];
while(left < right) {
while(left < right && arr[right] > pivot) {
right--;
}
while(left < right && arr[left] <= pivot) {
left++;
}
if(left < right) {
int p = arr[left];
arr[left] = arr[right];
arr[right] = p;
}
}
arr[start] = arr[left];
arr[left] = pivot;
return left;
}
public ArrayList<Integer> getLeastNumbers_Solution(int[] nums, int k) {
if (k > nums.length || k <= 0) {
return new ArrayList<>();
}
PriorityQueue<Integer> maxHeap = new PriorityQueue<>((o1, o2) -> o2 - o1);
for (int num : nums) {
maxHeap.add(num);
if (maxHeap.size() > k) {
maxHeap.poll();
}
}
return new ArrayList<>(maxHeap);
}
41、数据流中的中位数
/**
* 左边是大顶堆
*/
private PriorityQueue<Integer> left = new PriorityQueue<>((o1, o2) -> o2 - o1);
/**
* 右边是小顶堆
*/
private PriorityQueue<Integer> right = new PriorityQueue<>();
private int N = 0;
public void Insert(Integer num) {
//平均分配到两个堆
if (N % 2 == 0) {
//左边的原数小 插入元素不一定比左边的小 因此 先插入左边 调整堆 拿出左边最大元素 放入右边
left.add(num);
right.add(left.poll());
} else {
//同理
right.add(num);
left.add(right.poll());
}
N++;
}
public Double GetMedian() {
//因为先存在了右边 所以奇数时候 拿出右边的堆顶元素即可
if (N % 2 == 1) {
return (double)right.peek();
} else {
return (right.peek() + left.peek()) / 2.0;
}
}
42、连续子数组的最大和
public static int FindGreatestSumOfSubArray(int[] arr) {
if (arr.length == 0) {
return 0;
}
int max = Integer.MIN_VALUE;
int sum = 0;
for (int i=0, len=arr.length; i<len; i++) {
if (sum <= 0) {
sum = arr[i];
} else {
sum += arr[i];
}
max = Math.max(sum, max);
}
return max;
}
43、1~n中1出现的次数
/**
以位数为例,求解百位是1时候的情况
分为3中情况
一、百位 >= 2 例如 31256 312-a 56-b
满足条件的数
100~199
1100~1199
。。
31100~31999
百位为1的5位数 (a/10 + 1)* 100
a/10 + 1 0~31
* 100 0~31 每个数的末尾 可以是0~99 共100个
二、百位为1 例如 31156
满足条件
100~199
1100~1199
。。。
30100~30199
31100~31156
百位为1的5位数 (a/10)* 100 + (b+1)
a/10 0~30 31时候 后面是0~b 故 加(b+1)
三、百位为0 31056
100~199
1100~1199
。。。
30100~30199
百位为1的5位数 (a/10)* 100
百位 >= 2 31256 百位=2 a/10+1 = 31+1 == (a+8)/10 = 320 / 10 = 32
31343 百位=3 a/10+1 = 31+1 == (a+8)/10 = 321 / 10 = 32
+8会进位 不需要+1
故百位 >= 2 || 百位 == 0 ((a+8)/ 10)*100 进位,不需要加1
百位 == 1 (a+8)/ 10 +(b+1) 不会进位
*/
private static int numberOf1(int n) {
int count = 0;
//从个位开始考虑,再到十位,百位,千位
for (int i=1; i<=n; i*=10) {
int a = n/i;
int b = n%i;
count += (a + 8) /10 * i + (a % 10 == 1 ? (b+1) : 0);
}
return count;
}
44、数字序列中某一位的数字
private static int indexOf(int index) {
if (index < 0) {
return -1;
}
if (index <= 9) {
return index;
}
int i = 2;
index -= 10;
int n;
int num;
while (true) {
n = i * (int) Math.pow(10,(i-1)) * 9;
if (index >= n) {
index -= i * Math.pow(10,(i-1)) * 9;
i++;
} else {
num = calculateNum(index, i);
return num;
}
}
}
/**
* 计算是第几个数字 并取出那一位
* @param index
* @return
*/
private static int calculateNum(int index, int i) {
//m 个i位数
int m = index / i;
//第y位
int y = index % i;
//前面的数是m index落在 m+1的第y位
int num = (int) Math.pow(10,(i-1)) + (m - 1);
int x = num + 1;
int c = String.valueOf(x).charAt(y) - '0';
return c;
}
45、把数组排成最小的数
public static String PrintMinNumber(int [] numbers) {
String[] nums = new String[numbers.length];
for (int i=0, len=numbers.length; i<len; i++) {
nums[i] = String.valueOf(numbers[i]);
}
//最小
Arrays.sort(nums,(s1,s2) -> (s1 + s2).compareTo(s2 + s1));
//最大
//Arrays.sort(nums,(s2,s1) -> (s1 + s2).compareTo(s2 + s1));
String str = "";
for (String s : nums) {
str += s;
}
return str;
}
46、把数字翻译成字符串
/**
* 0翻译成“a”,1翻译成“b”…25翻译成“z”
* @param str
* @return
*/
public static int numCount(String str) {
int n = str.length();
int[] dp = new int[n+1];
dp[n] = 1;
for (int i=n-1; i>=1; i--) {
if (i == n-1) {
dp[i] = dp[i+1] + calculate(String.valueOf(str), i) * 1;
continue;
}
dp[i] = dp[i+1] + calculate(String.valueOf(str), i) * dp[i+2];
}
return dp[1];
}
/**
* 当前与前面能否组合 09 不能组合 56不能组合。。。
* @param str
* @param i
* @return
*/
private static int calculate(String str, int i) {
int num = Integer.valueOf(String.valueOf(str.charAt(i-1)) + String.valueOf(str.charAt(i)));
if (num >= 10 && num <= 25) {
return 1;
} else {
return 0;
}
}
/**
* 'A' -> 1
* 'B' -> 2
* ...
* 'Z' -> 26
* @param s
* @return
*/
public int numDecodings(String s) {
if (null == s || s.length() == 0) {
return 0;
}
int n = s.length();
int[] dp = new int[n + 1];
dp[0] = 1;
dp[1] = s.charAt(0) == '0' ? 0 : 1;
// substring 不含尾
for (int i = 2; i <= n; i++) {
int one = Integer.valueOf(s.substring(i - 1, i));
if (one != 0) {
dp[i] += dp[i - 1];
}
if (s.charAt(i - 2) == '0') {
continue;
}
int two = Integer.valueOf(s.substring(i - 2, i));
if (two <= 26) {
dp[i] += dp[i - 2];
}
}
return dp[n];
}
47、礼物的最大价值
/**
* getMost(i,j) = max(getMost(i-1,j),getMost(i,j-1)) + bord[i][j]
* 由此可见 跟本次计算有关的值只是前面一行的 那么 可以用一个一维数组来保存前面计算的最值
* j设置为中坐标 前面j个 (i,0) (i,1) (i,2)...(i,j-1) 保存本行前面的最大值
* (i-1,j) (i-1,j+1) (i-1,j+2) ... (i-1,n-1) 保存上一行的最大值
*/
public int getMost(int[][] board) {
if (null == board || board[0].length == 0 || board.length == 0) {
return 0;
}
int n = board[0].length;
int[] max = new int[n];
for (int[] v : board) {
max[0] += v[0];
for (int i=1; i<n; i++) {
max[i] = Math.max(max[i], max[i-1]) + v[i];
}
}
return max[n-1];
}
48、最长不含重读字符的子字符串
public static int longSubStrNoDuplicateChar(String str) {
int curLen = 0, maxLen = 0;
// 用来保存每个字符在前面出现的位置
int[] preChar = new int[26];
// 初始化所有值为-1
Arrays.fill(preChar, -1);
for (int curIndex=0; curIndex<str.length(); curIndex++) {
// a-0 b-1 c-2 记录字符出现的位置 preChar[0]放置a最近出现的位置 以此类推
int c = str.charAt(curIndex) - 'a';
// 当前字符第一次出现的位置
int preIndex = preChar[c];
if (c == -1 || curIndex - preIndex > curLen) {
// 该字符之前没有出现 或者虽然出现了 但是不在最长子串中
// 例如 abacadb cad+b 之前的b不构成影响
curLen++;
} else {
maxLen = Math.max(maxLen, curLen);
curLen = curIndex - preIndex;
}
// 更新字符最近出现的位置 abacadb a由0->2->4
preChar[c] = curIndex;
}
return Math.max(maxLen, curLen);
}
49、丑数
public static int GetUglyNumber_Solution(int N) {
//1 2 3 4 5 6 8
if (N <= 6) {
return N;
}
int i2 = 0, i3 = 0, i5 = 0;
int[] dp = new int[N];
dp[0] = 1;
for (int i = 1; i < N; i++) {
// 下一个丑数 肯定是前面的丑数乘 2 || 3 || 5 得到的 因为需要排序,所以需要最小的那个
int next2 = dp[i2] * 2, next3 = dp[i3] * 3, next5 = dp[i5] * 5;
dp[i] = Math.min(next2, Math.min(next3, next5));
if (dp[i] == next2) {
// dp[i] == next2 那么 dp[i2] * 2 已经是最小的了
// 说明前面的在不需要再计算了 因为它不会大于 dp[i2] * 2 说明已经在数组中了
i2++;
}
if (dp[i] == next3) {
// 同理
i3++;
}
if (dp[i] == next5) {
// 同理
i5++;
}
}
return dp[N - 1];
}
50、第一个只出现一次的字符
public int FirstNotRepeatingChar(String str) {
int[] arr = new int[256];
for(int i=0, len=str.length(); i<len; i++) {
arr[str.charAt(i)]++;
}
for(int i=0, len=str.length(); i<len; i++) {
if(arr[str.charAt(i)] == 1) {
return i;
}
}
return -1;
}
51、数组中的逆序对
//需要用long
long count = 0;
int[] temp;
public int InversePairs(int[] nums) {
temp = new int[nums.length];
mergeSort(nums, 0, nums.length-1);
return (int) (count % 1000000007);
}
private void mergeSort(int[] arr, int l, int h) {
if(l >= h) {
return;
}
int m = l + (h - l) / 2;
mergeSort(arr, l, m);
mergeSort(arr, m+1, h);
merge(arr, l, m, h);
}
private void merge(int[] nums, int l, int m, int h) {
int i=l, k=l, j=m+1;
while(i<=m || j<=h) {
if(i > m) {
// 右边有数据
temp[k] = nums[j++];
} else if(j > h) {
// 左边有数据
temp[k] = nums[i++];
} else if(nums[i] <= nums[j]) {
// 没有逆序对
temp[k] = nums[i++];
} else {
// nums[i] > nums[j] 那么nums[i]..nums[m] 都大于nums[j]
temp[k] = nums[j++];
count += m - i + 1;
}
k++;
}
// 调整数组 直到有序
for (k=l; k<=h; k++) {
nums[k] = temp[k];
}
}
52、两个链表的第一个公共节点
public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
ListNode l1 = pHead1;
ListNode l2 = pHead2;
while(l1 != l2) {
l1 = (l1 == null) ? pHead2 : l1.next;
l2 = (l2 == null) ? pHead1 : l2.next;
}
return l1;
}
53、在排序数组中查找数字
public int GetNumberOfK(int[] nums, int K) {
int first = binarySearch(nums, K);
int last = binarySearch(nums, K + 1);
return (first == nums.length || nums[first] != K) ? 0 : last - first;
}
private int binarySearch(int[] nums, int K) {
int l = 0, h = nums.length-1;
while (l <= h) {
int m = l + (h - l) / 2;
if (nums[m] >= K) {
h = m - 1;
} else {
l = m + 1;
}
}
return l;
}
54、二叉搜索树的第K大节点
private TreeNode result;
private int count = 0;
public TreeNode KthNode(TreeNode pRoot, int k) {
inOrder(pRoot, k);
return result;
}
private void inOrder(TreeNode root, int k) {
if (null == root || count >= k) {
return;
}
inOrder(root.left, k);
count++;
if (count == k) {
result = root;
}
inOrder(root.right, k);
}
55、二叉树的深度
public int TreeDepth(TreeNode root) {
if (root == null) {
return 0;
}
return Math.max(TreeDepth(root.left),TreeDepth(root.right)) + 1;
}
56、数组中数字出现的次数
//一个数字出现一次 其他数字出现3次
private static int getOne(int[] arr) {
int[] bitNum = new int[32];
for (int i=0, len=arr.length; i<len; i++) {
int bitMask = 1;
for (int j=31; j>=0; j--) {
//看该位置的数是0还是1
int bit = arr[i] & bitMask;
if (bit != 0) {
//如果是1 就加1
bitNum[j]++;
}
//左移一位
bitMask <<= 1;
}
}
int result = 0;
for (int i=0; i<32; i++) {
result = result << 1;
result += bitNum[i] % 3;
}
return result;
}
//只出现一次的两个数
public void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) {
int diff = 0;
for (int i : array) {
//结果为2个不相同数的异或结果
diff ^= i;
}
//负数 原码 -> 反码 -> 加一
// 5 0000 0101
// 7 0000 0111
// 5^7 0000 0010 结果是2
// 2 0000 0010
// 反码 1111 1101
// 加一 1111 1110
// -2 1111 1110 0000 0010
// 2&-2 0000 0010
// 得到出 diff 最右侧不为 0 的位,也就是不存在重复的两个元素在位级表示上最右侧不同的那一位
diff &= -diff;
for (int i : array) {
//i的低位是0
if ((i & diff) == 0) {
num1[0] ^= i;
} else {
num2[0] ^= i;
}
}
}
57、和为s的数字
//和为s的两个数字
public ArrayList<Integer> findNumbersWithSum(int [] array, int sum) {
ArrayList<Integer> list = new ArrayList<>();
if(array.length == 0 || null == array) {
return list;
}
int l = 0, h = array.length-1;
while(l < h) {
int mid = l + (h - l) / 2;
int t = array[l] + array[h];
if(t > sum) {
h--;
} else if(t < sum) {
l++;
} else {
list.add(array[l]);
list.add(array[h]);
break;
}
}
return list;
}
//和为s的连续正序列
public ArrayList<ArrayList<Integer>> findContinuousSequence(int sum) {
ArrayList<ArrayList<Integer>> ret = new ArrayList<>();
int small = 1;
int big = 2;
//至少两个数字 所以小的不能大于和的一半
int stop = (1+sum)/2;
int target = 3;
while(small < stop) {
if(target < sum) {
big++;
target += big;
} else if(target > sum) {
target -= small;
small++;
} else {
ArrayList<Integer> list = new ArrayList<>();
for(int i=small; i<=big; i++) {
list.add(i);
}
ret.add(list);
big++;
target += big;
}
}
return ret;
}
58、反转字符串
public static String ReverseSentence(String str) {
char[] chars = str.toCharArray();
int n = str.length();
//反转整个字符串 "I am a student."-->".tneduts a ma I"
reverseStr(chars,0,chars.length-1);
//再把反转的单词 反转回来
int l = 0, h = 0;
while (h <= n) {
if (h == n || chars[h] == ' ') {
// j==n-1 到最后一个字母了
// chars[j] == ' ' 是一个单词了
// h-1 遇到空格 要反转空格前面的 所以最后一个字母的时候 需要越界
// 例如abc是最后一个单词 需要让h回退到c上
reverseStr(chars, l , h-1);
l = h + 1;
}
h++;
}
return new String(chars);
}
/**
* 反转函数
* @param chars
*/
private static void reverseStr(char[] chars, int l, int h) {
while (l < h) {
char c = chars[l];
chars[l] = chars[h];
chars[h] = c;
l++;
h--;
}
}
59、队列的最大值
/**
* 通过维护大顶堆来完成
* @param num
* @param size
* @return
*/
public ArrayList<Integer> maxInWindowsHeap(int[] num, int size) {
ArrayList<Integer> list = new ArrayList<>();
if (size > num.length || size < 1) {
return list;
}
//构建大顶堆大顶堆
PriorityQueue<Integer> priorityQueue = new PriorityQueue<>((o1, o2) -> o2 - o1);
for (int i=0; i<size; i++) {
priorityQueue.add(num[i]);
}
//第一组的划窗的最大值
list.add(priorityQueue.peek());
//确保堆的大小为size
for (int i=0, j=i+size; j<num.length; i++,j++) {
//有新元素进入,先删除队列前面的值 因为其不在划窗范围内
priorityQueue.remove(num[i]);
//加入新进入划窗的元素,并且维持大顶堆
priorityQueue.add(num[j]);
list.add(priorityQueue.peek());
}
return list;
}
/**
* 暴力搜索 O(nk)
* @param num
* @param size
* @return
*/
public static ArrayList<Integer> maxInWindowsSearch(int [] num, int size) {
if (size == 0) {
return new ArrayList<>();
}
ArrayList<Integer> list = new ArrayList<>();
for (int i=0; i<num.length-size+1; i++) {
int[] arr = new int[size];
int index = 0;
for (int j=i; j<size+i; j++) {
arr[index] = num[j];
index++;
}
list.add(getMax(arr));
}
return list;
}
private static int getMax(int[] arr) {
int max = Integer.MIN_VALUE;
for (int i=0; i<arr.length; i++) {
max = max >= arr[i] ? max : arr[i];
}
return max;
}
60、n个骰子的点数
public List<Map<Integer, Double>> printProbability(int n) {
final int face = 6;
// 所有点数和
final int pointNum = face * n;
// 骰子数量 点数和
long[][] dp = new long[n + 1][pointNum + 1];
// 初始化 只有一个骰子时候的情况 i为点数 横坐标1个骰子(1,1) 纵坐标点数和(1,2)
for (int i = 1; i <= face; i++) {
dp[1][i] = 1;
}
//剩余的n-1个骰子
for (int i = 2; i <= n; i++) {
// j为点数和 使用i个骰子最小点数为i,每个骰子最小点是1
for (int j = i; j <= pointNum; j++) {
// 第i个骰子 点数为k->1-6
for (int k = 1; k <= face && k <= j; k++) {
// 点数为j 本次点数k 1-6 那么
// 前面的点数和 j-1 k=1, j-2 k=2, j-3 k=3, j-4 k=4, j-5 k=5, j-6 k=6
// 如果本次点数k=3 那么前面是j-3时候 和为j
dp[i][j] += dp[i - 1][j - k];
}
}
}
// 每个骰子出现的点数6种 2个骰子的所有点数可能 6*6 3个 6*6*6
final double totalNum = Math.pow(6, n);
List<Map<Integer, Double>> ret = new ArrayList<>();
for (int i = n; i <= pointNum; i++) {
Map<Integer ,Double> map = new HashMap<>();
map.put(i,dp[n][i] / totalNum);
ret.add(map);
}
return ret;
// 当有3个骰子的时候 首先记录第一个 然后第二个 第三个进来时候,依赖第二个,
// 故第一个的记录没用了,可以清除 时间复杂度下降到O(n)
public List<Map<Integer, Double>> printProbability2(int n) {
final int face = 6;
final int pointNum = face * n;
long[][] dp = new long[2][pointNum + 1];
// 初始化 只有一个骰子的时候
for (int i = 1; i <= face; i++) {
dp[0][i] = 1;
}
// 循环利用的标记 不需要记录所有 只需要在前一个的基础上继续操作即可
int flag = 1;
// 剩余的n-1个骰子
for (int i = 2; i <= n; i++,flag = 1 - flag) {
// 清除
for (int j = 0; j <= pointNum; j++) {
dp[flag][j] = 0;
}
for (int j = i; j <= pointNum; j++) {
for (int k = 1; k <= face && k <= j; k++) {
// 清除之后 存入新的
dp[flag][j] += dp[1 - flag][j - k];
}
}
}
final double totalNum = Math.pow(6, n);
List<Map<Integer, Double>> ret = new ArrayList<>();
for (int i = n; i <= pointNum; i++) {
Map<Integer, Double> map = new HashMap<>();
map.put(i, dp[1-flag][i] / totalNum);
ret.add(map);
}
return ret;
}
61、扑克牌中的顺子
public static boolean isContinuous(int [] numbers) {
if(numbers.length != 5 || numbers == null) {
return false;
}
Arrays.sort(numbers);
// 统计0的个数 也就是大小王的个数 注意 这里的大小王不一定是2个,可能是5个
int count0 = 0;
for(int i=0; i<5; i++) {
if(numbers[i] == 0) {
count0++;
}
}
// 统计距离顺子,相差多少 是否可以用王来弥补
int countDitance = 0;
for(int i=0; i<4; i++) {
if(numbers[i] != 0) {
// 有对子 不能成顺子 对子不是大小王
if(numbers[i] == numbers[i+1]) {
return false;
}
int x = numbers[i+1] - numbers[i];
countDitance += x > 1 ? x-1 : 0;
}
}
return countDitance <= count0;
}
62、圆圈中最后剩下的数字
public int LastRemaining_Solution(int n, int m) {
LinkedList<Integer> linkedList = new LinkedList<>();
for (int i=0; i<n; i++) {
linkedList.add(i);
}
int i = 0;
while (linkedList.size() > 1) {
i = (i + m - 1) % linkedList.size();
linkedList.remove(i);
}
return linkedList.size() == 1 ? linkedList.get(0) : -1;
}
63、股票的最大利润
public int maxDiff(int[] arr) {
if(arr.length <= 1) {
return 0;
}
int min = arr[0];
int maxDiff = Integer.MIN_VALUE;
for (int i=1, len=arr.length; i<len; i++) {
if (arr[i] < min) {
min = arr[i];
}
int t = arr[i] - min;
maxDiff = Math.max(maxDiff, t);
}
return maxDiff;
}
64、求 1+2+3+。。。+n
public int Sum_Solution(int n) {
int sum = n;
// && 能够短路 故可以作为递归结束条件
boolean flag = (n > 0) && ((sum += Sum_Solution( n - 1)) > 0);
return sum;
}
65、不用加减乘除做加法
/**
* 第一步:不考虑进位 1+1=0 0+0=0 0+1=1 1+0=1 异或可以得到这样的结果
* 第二步:考虑进位 1+1=10 0+0=0 1+0=1 0+1=1 与运算,并左移一位
* 第三步:前面两步的结果相加
* 结束条件:不产生进位 那么说明第一步时候,就搞定了
*/
public static int Add(int num1,int num2) {
int sum, carry;
while(num2 != 0){
sum = (num1 ^ num2);
carry = (num1 & num2) << 1;
num1 = sum;
num2 = carry;
}
return num1;
}
66、构建乘积数组
//暴力破解
public static int[] multiply1(int[] A) {
int[] b = new int[A.length];
//注意需要填充1,否则当前值为0,所有乘积都是0
Arrays.fill(b,1);
int index = 0;
while(index < A.length) {
for(int i=0; i<index; i++) {
b[index] *= A[i];
}
for(int i=index+1; i<A.length; i++) {
b[index] *= A[i];
}
index++;
}
return b;
}
//大神的巧妙解法
public static int[] multiply2(int[] A) {
int n = A.length;
int[] B = new int[n];
// B[i] = A[0]*A[1]*A[2]*..*A[i-1]
for (int i = 0, product = 1; i < n; product *= A[i], i++) {
// product是前面数的乘积
B[i] = product;
}
// product是后面A[i+1] ... A[n-1]的乘积
for (int i = n - 1, product = 1; i >= 0; product *= A[i], i--) {
// 再乘以前面的结果
B[i] *= product;
}
return B;
}
67、把字符串转换成整数
public static int StrToInt(String str) {
if (null == str || str.length() == 0) {
return 0;
}
boolean isNegative = str.charAt(0) == '-';
int num = 0;
for (int i = 0; i < str.length(); i++) {
char c = str.charAt(i);
// 第一位是符号 不做处理
if (i == 0 && (c == '+' || c == '-')) {
continue;
}
// 不合法
if (c < '0' || c > '9') {
return 0;
}
num = num * 10 + c - '0';
}
return isNegative ? -num : num;
}