模拟乘法
不能直接用Long,问题在于会出现溢出的情况。
只能手动模拟相乘的情况
class Solution {
public String multiply(String num1, String num2) {
if (num1.equals("0") || num2.equals("0")) {
return "0";
}
String ans = "0";
int m = num1.length(), n = num2.length();
for (int i = n - 1; i >= 0; i--) {
StringBuffer curr = new StringBuffer();
int add = 0;
for (int j = n - 1; j > i; j--) {
curr.append(0); // 模拟× 10 的场景
}
int y = num2.charAt(i) - '0';
for (int j = m - 1; j >= 0; j--) {
int x = num1.charAt(j) - '0';
int product = x * y + add;
curr.append(product % 10);
add = product / 10;
}
if (add != 0) {
curr.append(add % 10);
}
ans = addStrings(ans, curr.reverse().toString());
}
return ans;
}
public String addStrings(String num1, String num2) {
int i = num1.length() - 1, j = num2.length() - 1, add = 0;
StringBuffer ans = new StringBuffer();
while (i >= 0 || j >= 0 || add != 0) {
// add直接在这里处理
int x = i >= 0 ? num1.charAt(i) - '0' : 0; // 防止越位以及最后判断谁越位
int y = j >= 0 ? num2.charAt(j) - '0' : 0;
int result = x + y + add;
ans.append(result % 10); // 本次添加余数
add = result / 10; // 留给下次的是本次的结果
i--;
j--;
}
ans.reverse();
return ans.toString();
}
}
更直接的:
BigDecimal n1 = new BigDecimal(num1);
BigDecimal n2 = new BigDecimal(num2);
BigDecimal res = n1.multiply(n2);
return res.toPlainString();
149.直线上最多的点树
Y=kx + b
求出所有的kb,两个点决定一个kb,n的平方的遍历
然后枚举哪些坐标满足计算公式
求出最大的数目
模拟幂次
https://leetcode-cn.com/problems/powx-n/
class Solution {
public double myPow(double x, int n) {
long N = n;
return N >= 0 ? quickMul(x, N) : 1.0 / quickMul(x, -N);
}
public double quickMul(double x, long N) {
if (N == 0) {
return 1.0;
}
double y = quickMul(x, N / 2);
return N % 2 == 0 ? y * y : y * y * x;
}
}
原地hash
https://leetcode-cn.com/problems/find-all-duplicates-in-an-array/
解题思路
要不使用额外内存空间,则只能原地修改数组元素来标记是否访问过
原理:如果是相同的元素,那么以他们为索引的元素值一定是同一个值,因此可以修改该值来标记是否被访问过
注意:既要原地修改元素,就不能影响其自身作为索引的访问,那么只有一种办法,那就是将该元素取反,或者加减某个数,在访问的时候,再通过取正或者加减某个数还原回来
利用index与a[index]之间的关系
即取该元素值n,然后将a[abs(n)]取反。
如果下次遇到发现a[abs(n)]是负数,说明之前访问过。直接加入结果集。
位运算
有点类似hash的思路,用位来表征状态
求子集的题目:
https://leetcode-cn.com/problems/subsets/solution/zi-ji-by-leetcode-solution/
核心思路:
- 暴力搜索
- 用位来表示对应位置的数组是否启用
核心代码:
for (int mask = 0; mask < (1 << n); ++mask) {
t.clear();
for (int i = 0; i < n; ++i) {
if ((mask & (1 << i)) != 0) {
t.add(nums[i]);
}
}
ans.add(new ArrayList<Integer>(t));
}
代码:
class Solution {
List<Integer> t = new ArrayList<Integer>();
List<List<Integer>> ans = new ArrayList<List<Integer>>();
public List<List<Integer>> subsets(int[] nums) {
int n = nums.length;
for (int mask = 0; mask < (1 << n); ++mask) {
t.clear();
for (int i = 0; i < n; ++i) {
if ((mask & (1 << i)) != 0) {
t.add(nums[i]);
}
}
ans.add(new ArrayList<Integer>(t));
}
return ans;
}
}
暴力解法:小问题的解构成大问题的解
在已经有的集合上新加入元素变成新的集合再扔进去。
191.位1的个数
https://leetcode-cn.com/problems/number-of-1-bits/
要点:
- 32位以内,即<<1的操作最多32次
https://leetcode-cn.com/problems/number-of-1-bits/solution/wei-1de-ge-shu-by-leetcode/
public int hammingWeight(int n) {
int bits = 0;
int mask = 1;
for (int i = 0; i < 32; i++) {
// 最多32次
if ((n & mask) != 0) {
bits++; // 为1的位数
}
mask <<= 1;
}
return bits;
}
与运算符用符号“&”表示,其使用规律如下:
两个操作数中位都为1,结果才为1,否则结果为0,例如下面的程序段。
129&128 = 128。 “a”的值是129,转换成二进制就是10000001,而“b”的值是128,转换成二进制就是10000000。根据与运算符的运算规律,只有两个位都是1,结果才是1,可以知道结果就是10000000,即128。
排序有关记录
- 任务调度器:执行有冷却时间命令的最短时间。621
https://leetcode-cn.com/problems/task-scheduler/
解法一:排序。排序是为了确认优先级,每轮第一个消除的是最大值的元素。 - 合并公共区间:https://leetcode-cn.com/problems/merge-intervals/solution/zhen-dui-xin-shou-jian-ji-yi-dong-de-ti-jie-liang-/
排序加比较后的合并。
另一种解法:boolean数组做标记,这种解法无法处理一种情况:[1,4][5,6],这种不算做有公共区间。 - 两个有序的自定义链表合并:https://leetcode-cn.com/problems/merge-two-sorted-lists/solution/he-bing-liang-ge-you-xu-lian-biao-by-leetcode/
- 原地排序的双指针法: https://leetcode-cn.com/problems/remove-duplicates-from-sorted-array/submissions/