829 连续整数求和 zy 数学
给定一个正整数 N,试求有多少组连续正整数满足所有数字之和为 N?
输入: 5
输出: 2
解释: 5 = 5 = 2 + 3,共有两组连续整数([5],[2,3])求和后为 5。
2N=k(2x+k+1) 可以枚举[1,2N]的k超时
- k < 2x + k + 1 所以k<
sqrt(2N)
- k 和 2x + k + 1 的奇偶性不同,问题就转变为有多少组奇偶性不同的b和c满足:2N = b*c
循环数组找一个数
如何用最少的步骤称出13颗1g砝码中的赝品
https://blog.csdn.net/zhtengsh/article/details/38879431
一个圆中三个点构成一个锐角三角形的概率
圆内接三角形的最大角至少要大于等于60度,该最大角的范围可从60到180度变化,但只有60到90间为锐角,所以占1/4.
字节流和字符流,读取一个配置文件读一行 写入数据库
two sum
如果数字在最后怎么优化
如果有序two sum怎么做
three sum
String2Integer
16 快速排序
基本:
最普通的,每次取[0]作子集划分s1+[0]+s2,再递归两个子集。
最坏情况123456 O(n^2)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20private void qS(int[] arr,int left,int right){
if(left>=right)return;
int pivot = arr[right];
// 因为保证i最后在左集合右边 用++i
// 所以初始化的时候边界都向外扩一格
int i = left-1;int j = right;
while (true){
// 关键 i<j
while (++i<j && arr[i] <= pivot);
while (--j>i && arr[j] >= pivot);
if(i < j){
swap(arr,i , j);
}
else break;
}
// 把主元放到左集合右边
swap(arr, i, right);
qS(arr, left, i-1);
qS(arr, i+1,right);
}
注意1:
主元:1取头、中、尾的中位数比随机函数便宜。
用ifelse判断这三个数,1)把最小的放到左边2)把最大的放到右边3)把中间的数替换到最后位置上pivot = nums[n-1]
然后用pivot划分子集,i从左开始,j从右开始,i最后停在j右边,交换[i],[n-1]
,pivot放了正确的位置。
注意2:
如果有重复元素 如果11111,
1)重复元素也交换,最后pivot也会被换到中间,很等分nlogn。
2)不交换,i直接比较到最后,pivot还是在最后,变成n^2
注意3:
小规模数据集(N不到100可能还不如插入排序)
当递归的长度够小直接插入排序。
JDK Arrays.sort()
中的根据阈值从merge,quick,insert,count sort中选一个
1 | /**如果数组长度小于 this, Quicksort 优先于 merge sort.*/ |
17 堆排序 不需要额外空间 大顶堆
堆(数组实现的完全二叉树)
左孩子是(1+i<<1)
// 1+i<<2 奇数
右孩子是(i+1)<<1
//偶数
父节点是(i-1)>>1
堆排序:
线性复杂度将数组调成最大堆O(n),将堆顶和数组最后交换,堆规模-1,再调成最大堆。
1 | heapify(arr); |
建堆方法1:
从上到下,每个新加的结点放在最右下,然后shiftUp每个 复杂度O(nlogn) (都可以做全排序了)
正确方法:
思路:
每个叶节点都成一个子堆,下滤操作能完成两个子堆的合并。
1 | //大顶堆 |
复杂度:
复杂度每个节点只需要比较的长度最多是这个节点到叶子的高度(而不是在树中的深度)。O(N)的
因为二叉树越底层节点越多。深度越高节点越多,所以上滤复杂度高。
从右下开始依次下滤,所有叶子节点都不用下滤。
如果全堆大小为n,内部节点最后一个的idx是(n/2)-1
例子:一共9个节点 各层1,2,4,2个。最后一个内部节点是3,它的右边和下面都是叶子。
向堆添加节点(添加在数组最后,上滤)1
2
3
4
5
6
7
8
9
10
11private void shifUp(int[] arr,int i,int x){
while (i>0){
int parent = (i-1)>>>1;
int e = arr[parent];
if(e >= x)break;
// 下移父节点
arr[i] = e;
i = parent;
}
arr[i] = x;
}
32 递归冒泡排序
1 | public void bubblesort(int[] array,int n) { |
37 二分
2.[0,len) 保持len取不到
[0]:l=0,r=1,l++,while(l==r)的时候应该结束
好处:len就是长度[a,a+len),[a,b)+[b,c)=[a,c),[a,a)是空的1
2
3
4
5
6
7
8
9
10
11
12
13
14int l = 0,r = n;
while(l<r){
int mid = l+(r-l)/2;
if(arr[mid]==target)return mid;
if(arr[mid]>target){
//在左边,边界为取不到的数
r=mid;//[l,mid)
}else{
//左闭又开
l = mid+1;//[mid+1,r)
}
}
//如果l==r [1,1)表示空的
return -1;
42 2进制字符串转16进制
1 | String b2h(String bins){ |
43 !十进制转2进制
没有oj过1
2
3
4
5
6
7
8public String D2Bin(int de){
StringBuilder sb = new StringBuilder();
while (de != 0){
sb.insert(0,de&1);
de >>>= 1;
}
return sb.toString();
}
44 编辑距离
1)定义dp[n][m]
表示从s1的前n个字符->s2的前m个字符最少的编辑距离。
2)加一个:[n-1][m]+1
减一个: [n][m-1]+1
变一个:[n-1][m-1] +1
相等:[n-1][m-1]1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17public int minDistance(String word1, String word2) {
int n = word1.length();
int m = word2.length();
int[][] dp = new int[n+1][m+1];
for(int i =0;i<=n;i++){dp[i][0] = i;}
for(int i =0;i<=m;i++){dp[0][i] = i;}
for(int i =1;i<=n;i++){
for(int j = 1;j<=m;j++){
if(word1.charAt(i-1) == word2.charAt(j-1)){
dp[i][j] = dp[i-1][j-1];
}else {
dp[i][j] = Math.min(Math.min(dp[i-1][j]+1,dp[i][j-1]+1),dp[i-1][j-1]+1);
}
}
}
return dp[n][m];
}
二维数组搜索
1 | public boolean searchMatrix(int[][] matrix, int target) { |
矩阵旋转90度 lc 48
逆时针:第一步交换主对角线两侧的对称元素,第二步交换第i行和第n-1-i行,即得到结果。 如果是顺时针, 第一步交换对角线两侧的对称元素,第二步交换第i行和第n-1-i行,即得到结果。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19public void rotate(int[][] matrix) {
int n = matrix.length;
for(int i = 0;i<n;i++){
for(int j = i+1;j<n;j++){
if(i!=j){
int tmp = matrix[i][j];
matrix[i][j] = matrix[j][i];
matrix[j][i] = tmp;
}
}
}
for(int i =0;i<n;i++){
for(int j = 0;j<n/2;j++){
int tmp = matrix[i][j];
matrix[i][j] = matrix[i][n-1-j];
matrix[i][n-1-j] = tmp;
}
}
}
人民币转换
链接:https://www.nowcoder.com/questionTerminal/00ffd656b9604d1998e966d555005a4b?commentTags=Java
输入一个double数
输出人民币格式
1、中文大写金额数字前应标明“人民币”字样。中文大写金额数字应用壹、贰、叁、肆、伍、陆、柒、捌、玖、拾、佰、仟、万、亿、元、角、分、零、整等字样填写。(30分)
2、中文大写金额数字到“元”为止的,在“元”之后,应写“整字,如¥ 532.00应写成“人民币伍佰叁拾贰元整”。在”角“和”分“后面不写”整字。(30分)
3、阿拉伯数字中间有“0”时,中文大写要写“零”字,阿拉伯数字中间连续有几个“0”时,中文大写金额中间只写一个“零”字,如¥6007.14,应写成“人民币陆仟零柒元壹角肆分“。(
151121.15
人民币拾伍万壹仟壹佰贰拾壹元壹角伍分
思路:整数部分:
1)每个数字都是单位+数字(元+个位,十拾十位),
2)单位顺序完整应该是
【”元”, “拾”, “佰”, “仟”, “万”, “拾”, “佰”, “仟”, “亿”, “拾”, “佰”, “仟”】
3)对批量0做flag。
4)如果14去掉1其它都ok。
小数部分题目要求0角1分不用输出角则暴力
1 | public class Main { |
快速排序
24 两个一组反转链表
Given 1->2->3->4, you should return the list as 2->1->4->3.
1 | public ListNode swapPairs(ListNode head) { |
11 选两点容纳的水面积最大
Input: [1,8,6,2,5,4,8,3,7]
Output: 49
1 | public int maxArea(int[] height) { |
42 雨水 水槽问题
Input: [0,1,0,2,1,0,1,3,2,1,2,1]
Output: 6
正确做法:双指针1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21public int trap(int[] A){
int a=0;
int b=A.length-1;
int max=0;
// 关键
int leftmax=0;
int rightmax=0;
while(a<=b){
leftmax=Math.max(leftmax,A[a]);
rightmax=Math.max(rightmax,A[b]);
if(leftmax<rightmax){
max+=(leftmax-A[a]);
a++;
}
else{
max+=(rightmax-A[b]);
b--;
}
}
return max;
}
两个数组做法:left保存当前位置左边的max。right保存当前位置右边的max。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18public int trap(int[] height) {
int n = height.length;
int[] left = new int[n];
int[] right = new int[n];
for(int i = 1;i<n;i++){
left[i] = Math.max(left[i-1],height[i-1]);
}
for(int i = n-2;i>=0;i--){
right[i] = Math.max(right[i+1],height[i+1]);
}
int rst = 0;
for(int i = 0;i<n;i++){
int tmp = Math.min(left[i],right[i]) - height[i];
if(tmp >0)
rst += tmp;
}
return rst;
}
146 LRU cache HashMap<Integer,DoubleLinkedList>
Cache replacement policies
least recently used cache最近最少使用缓存
java:LinkedHashMap:
https://docs.oracle.com/javase/8/docs/api/java/util/LinkedHashMap.html#removeEldestEntry-java.util.Map.Entry-
双向链表+hashmap
1 | public class LRUCache { |
946 栈顺序
Input: pushed = [1,2,3,4,5], popped = [4,5,3,2,1]
Output: true
1 | public boolean validateStackSequences(int[] pushed, int[] popped) { |
206反转链表
空间是n1
2
3
4
5
6
7
8public ListNode reverseList(ListNode head) {
if(head == null || head.next == null)return head;
ListNode second = reverseList(head.next);
// 1->(second:7->6->5..->2) (second:7->6->5..->2) ->1->null
head.next.next = head;
head.next = null;
return second;
}
迭代空间是1:
三个指针pre(注意初始为null),cur,next(只用于cur跳跃),用cur控制结束,一个暂存三个赋值。1
2
3
4
5
6
7
8
9
10
11
12public ListNode reverseList(ListNode head) {
if(head == null || head.next == null)return head;
ListNode prev = null;
ListNode curr = head;
while(curr != null){
ListNode next = curr.next;
curr.next = prev;
prev = curr;
curr = next;
}
return prev;
}
少一个指针 正确做法1
2
3
4
5
6
7
8
9
10
11public ListNode reverseList(ListNode head) {
if(head == null || head.next == null)return head;
ListNode cur = null;
while(head!=null){
ListNode next = head.next;
head.next = cur;
cur = head;
head = next;
}
return cur;
}
python1
2
3
4
5def reverseList(self, head):
cur,prev = head,None
while cur:
cur.next,prev,cur = prev,cur,cur.next
return prev
转成栈浪费空间并且代码复杂
141链表环检测
空间O(1) 快慢指针:快指针走2步,慢指针走一步,当快指针遇到慢指针
最坏情况,快指针和慢指针相差环长q -1步
1 | class Solution{ |
142 环起始于哪个node
1->2->3->4->5->6->7->3 meet:6
a: 从head到环
b:快指针走了两次的环内距离(慢指针到环起点的距离)
c: 慢指针没走完的环内距离
已知快指针走的距离是slow的两倍
慢=a+b 快=a+2b+c
则a=c
从len(head - 环起点) == 慢指针没走完的环距离
head与慢指针能在环起点相遇。1
2
3
4
5
6
7if(slow==fast){
while(head!=slow){
head=head.next;
slow=slow.next;
}
return slow;
}