1,数学运算
50,Pow(x, n)
题目:实现 pow(x,n) ,即计算
x
的整数n
次幂函数(即,)。
思路:使用折半计算,每次把n缩小一半,这样n最终会缩小到0,任何数的0次方都为1,这时候我们再往回乘,如果此时n是偶数,直接把上次递归得到的值算个平方返回即可,如果是奇数,则还需要乘上个x的值。还有一点需要引起我们的注意的是n有可能为负数,对于n是负数的情况,我们可以先用其绝对值计算出一个结果再取其倒数即可。我们让i初始化为n,然后看i是否是2的倍数,是的话x乘以自己,否则res乘以x,i每次循环缩小一半,直到为0停止循环。最后看n的正负,如果为负,返回其倒数。
class Solution { public double myPow(double x, int n) { double res = 1.0; for(int i = n; i != 0; i /= 2){ if(i % 2 != 0){ res *= x; } x *= x; } return n < 0 ? 1 / res : res; } }
69,x的平方根
题目:给你一个非负整数 x ,计算并返回 x 的 算术平方根 。由于返回类型是整数,结果只保留 整数部分 ,小数部分将被 舍去 。
class Solution { public int mySqrt(int num) { int left = 1; int right = num; int middle = 0; while (left <= right) { middle = left + (right - left) / 2; int temp = num / middle; if (temp > middle) { left = middle + 1; } else if (temp < middle) { right = middle - 1; } else if (temp == middle) { return middle; } } return right; } }
279,完全平方数
题目:给你一个整数
n
,返回 和为n
的完全平方数的最少数量 。完全平方数 是一个整数,其值等于另一个整数的平方;换句话说,其值等于一个整数自乘的积。例如,1
、4
、9
和16
都是完全平方数,而3
和11
不是。思路:判断完全平方数+背包问题
class Solution { public int numSquares(int n) { ArrayList arrayList = new ArrayList(); for (int i = 1; i <= n; i++) { if (isPerfectSquare(i)) { arrayList.add(i); } } Integer[] a = (Integer[]) arrayList.toArray(new Integer[arrayList.size()]); return coinChange(a, n); } public boolean isPerfectSquare(int num) { if (num == 1) { return true; } if (num == 2) { return false; } int left = 1; int right = num; while (left <= right) { int middle = left + (right - left) / 2; int temp = num / middle; if (temp > middle) { left = middle + 1; } else if (temp < middle) { right = middle - 1; } else if (temp == middle) { if (num % middle == 0) return true; left = middle + 1; } } return false; } public int coinChange(Integer[] coins, int amount) { int max = amount + 1; int[] dp = new int[amount + 1]; Arrays.fill(dp, max); dp[0] = 0; for (int i = 1; i <= amount; i++) { for (int j = 0; j < coins.length; j++) { if (coins[j] <= i) { dp[i] = Math.min(dp[i], dp[i - coins[j]] + 1); } } } return dp[amount] > amount ? -1 : dp[amount]; } }
367,有效的完全平方数
题目:给定一个 正整数
num
,编写一个函数,如果num
是一个完全平方数,则返回true
,否则返回false
。思路:加法防溢出,乘法防溢出。
class Solution { public boolean isPerfectSquare(int num) { if (num==1){ return true; } if (num==2){ return false; } int left = 1; int right = num; while (left <= right) { int middle = left+(right-left)/2; int temp = num/middle; if (temp > middle) { left=middle+1; }else if (temp<middle){ right=middle-1; }else if (temp==middle){ if (num%middle == 0) return true; left = middle + 1; } } return false; } }
399,除法求值
题目:给你一个变量对数组
equations
和一个实数值数组values
作为已知条件,其中equations[i] = [Ai, Bi]
和values[i]
共同表示等式Ai / Bi = values[i]
。每个Ai
或Bi
是一个表示单个变量的字符串。另有一些以数组queries
表示的问题,其中queries[j] = [Cj, Dj]
表示第j
个问题,请你根据已知条件找出Cj / Dj = ?
的结果作为答案。返回 所有问题的答案 。如果存在某个无法确定的答案,则用
-1.0
替代这个答案。如果问题中出现了给定的已知条件中没有出现的字符串,也需要用-1.0
替代这个答案。注意:输入总是有效的。你可以假设除法运算中不会出现除数为 0 的情况,且不存在任何矛盾的结果。
class Solution { public double[] calcEquation(List<List<String>> equations, double[] values, List<List<String>> queries) { int cnt=0; //哈希预处理 HashMap<String,Integer> map=new HashMap<>(); int n=equations.size(); for(int i=0;i<n;i++){ for(int j=0;j<2;j++){ if(!map.containsKey(equations.get(i).get(0))) map.put(equations.get(i).get(0),cnt++); if(!map.containsKey(equations.get(i).get(1))) map.put(equations.get(i).get(1),cnt++); } } //建图预处理 double [][] graph=new double [cnt][cnt]; for(int i=0;i<cnt;i++){ Arrays.fill(graph[i],-1.0); } //建图,乘积 for(int i=0;i<n;i++){ int va=map.get(equations.get(i).get(0)); int vb=map.get(equations.get(i).get(1)); graph[va][vb]=values[i]; graph[vb][va]=1.0/values[i]; } //Floyd算法 for(int k=0;k<cnt;k++){ for(int i=0;i<cnt;i++){ for(int j=0;j<cnt;j++){ if(graph[i][k]>0&&graph[k][j]>0) graph[i][j]=graph[i][k]*graph[k][j]; } } } //获取结果 int m=queries.size(); double [] res=new double [m]; for(int i=0;i<m;i++){ List<String> query=queries.get(i); double tmp=-1.0; if(map.containsKey(query.get(0))&&map.containsKey(query.get(1))){ int va=map.get(query.get(0)); int vb=map.get(query.get(1)); if(graph[va][vb]>0) tmp=graph[va][vb]; } res[i]=tmp; } return res; } }
989,数组形式的整数加法
题目:整数的 数组形式 num 是按照从左到右的顺序表示其数字的数组。例如,对于 num = 1321 ,数组形式是 [1,3,2,1] 。给定 num ,整数的 数组形式 ,和整数 k ,返回 整数 num + k 的 数组形式 。
class Solution { public List<Integer> addToArrayForm(int[] num, int k) { int kk = k; ArrayList arrayList = new ArrayList(); int i = num.length - 1; boolean flag = false; while (k != 0 && i != -1) { int temp = k % 10; k /= 10; int a = temp + num[i]; if (flag) { a++; } if (a >= 10) { a -= 10; flag = true; } else { flag = false; } arrayList.add(a); i--; } if (num.length > (kk + "").length()) { for (; i >= 0; i--) { int a = num[i]; if (flag) { a++; } if (a >= 10) { a -= 10; flag = true; } else { flag = false; } arrayList.add(a); } } else if (num.length < (kk + "").length()) { while (k != 0) { int a = k % 10; k /= 10; if (flag) { a++; } if (a >= 10) { a -= 10; flag = true; } else { flag = false; } arrayList.add(a); } } if (flag){ arrayList.add(1); } Collections.reverse(arrayList); return arrayList; } }
1281,整数的各位积和之差
题目:给你一个整数
n
,请你帮忙计算并返回该整数「各位数字之积」与「各位数字之和」的差。class Solution { public int subtractProductAndSum(int n) { int muti = 1; int sum = 0; while(n!=0){ muti *=n%10; sum +=n%10; n/=10; } return muti-sum; } }
1822,数组元素积的符号
题目:已知函数 signFunc(x) 将会根据 x 的正负返回特定值:
- 如果 x 是正数,返回 1 。
- 如果 x 是负数,返回 -1 。
- 如果 x 是等于 0 ,返回 0 。
给你一个整数数组 nums 。令 product 为数组 nums 中所有元素值的乘积。
思路:统计正数个数,负数个数,决不能乘积完判断大小,溢出。
class Solution { public int arraySign(int[] nums) { int result = 1; for (int i = 0; i < nums.length; i++) { if (nums[i]==0){ return 0; }else if (nums[i]>0){ result*=1; }else if (nums[i]<0){ result*=-1; } } return result; } }
2,奇怪数字
92,3,5,7乘积组合
题目:有些数的素因子只有 3,5,7,请设计一个算法找出第 k 个数。注意,不是必须有这些素因子,而是必须不包含其他的素因子。例如,前几个数按顺序应该是 1,3,5,7,9,15,21。
class Solution { public int getKthMagicNumber(int k) { int[] dp = new int[k + 1]; dp[1] = 1; int p3 = 1, p5 = 1, p7 = 1; for (int i = 2; i <= k; i++) { int num3 = dp[p3] * 3, num5 = dp[p5] * 5, num7 = dp[p7] * 7; dp[i] = Math.min(Math.min(num3, num5), num7); if (dp[i] == num3) { p3++; } if (dp[i] == num5) { p5++; } if (dp[i] == num7) { p7++; } } return dp[k]; } }
202,快乐数
题目:编写一个算法来判断一个数
n
是不是快乐数。如果n
是 快乐数 就返回true
;不是,则返回false
。
- 对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。
- 然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。
- 如果这个过程 结果为 1,那么这个数就是快乐数。
class Solution { public boolean isHappy(int n) { for (int i = 0; i < 30; i++) { int temp = 0; while (n > 0) { temp += (n % 10) * (n % 10); n /= 10; } if (temp == 1) { return true; } else { n = temp; } } return false; } }
264,丑数 II
题目:我们把只包含质因子 2、3 和 5 的数称作丑数(Ugly Number)。求按从小到大的顺序的第 n 个丑数。
思路:这个题用三指针,第一个丑数是1,以后的丑数都是基于前面的小丑数分别乘2,3,5构成的。我们每次添加进去一个当前计算出来个三个丑数的最小的一个,并且是谁计算的,谁指针就后移一位。
public class NthUglyNumber { public int nthUglyNumber(int n) { if (n <= 0) return -1; int[] dp = new int[n]; dp[0] = 1; int id2 = 0, id3 = 0, id5 = 0; for (int i = 1; i < n; i++) { dp[i] = Math.min(dp[id2] * 2, Math.min(dp[id3] * 3, dp[id5] * 5)); // 这里不用else if的原因是有可能id2(3) * 2 == id3(2) * 3 // 这种情况两个指针都要后移 if (dp[id2] * 2 == dp[i]) id2 += 1; if (dp[id3] * 3 == dp[i]) id3 += 1; if (dp[id5] * 5 == dp[i]) id5 += 1; } return dp[n - 1]; } }
274,H指数
题目:给你一个整数数组 citations ,其中 citations[i] 表示研究者的第 i 篇论文被引用的次数。计算并返回该研究者的 h 指数。
根据维基百科上 h 指数的定义:h 代表“高引用次数” ,一名科研人员的 h 指数 是指他(她)至少发表了 h 篇论文,并且每篇论文 至少 被引用 h 次。如果 h 有多种可能的值,h 指数 是其中最大的那个。
class Solution { public int hIndex(int[] citations) { Arrays.sort(citations); if (citations.length == 1) { return citations[0] >= 1 ? 1 : 0; } int left = 0; int right = citations.length; int middle = 0; int ans = 0; while (left < right) { middle = left + (right - left) / 2; int temp = citations.length - middle; if (temp > citations[middle]) { left = middle + 1; } else { right = middle; } } return citations.length - left; } }
275,H指数 II
题目:给你一个整数数组 citations ,其中 citations[i] 表示研究者的第 i 篇论文被引用的次数,citations 已经按照 升序排列 。计算并返回该研究者的 h 指数。
h 指数的定义:h 代表“高引用次数”(high citations),一名科研人员的 h 指数是指他(她)的 (n 篇论文中)总共有 h 篇论文分别被引用了至少 h 次。且其余的 n - h 篇论文每篇被引用次数 不超过 h 次。
提示:如果 h 有多种可能的值,h 指数 是其中最大的那个。请你设计并实现对数时间复杂度的算法解决此问题。
class Solution { public int hIndex(int[] citations) { if (citations.length == 1) { return citations[0] >= 1 ? 1 : 0; } int left = 0; int right = citations.length; int middle = 0; int ans = 0; while (left < right) { middle = left + (right - left) / 2; int temp = citations.length - middle; if (temp > citations[middle]) { left = middle + 1; } else { right = middle; } } return citations.length-left; } }
1201,丑数 III
题目:给你四个整数:
n
、a
、b
、c
,请你设计一个算法来找出第n
个丑数。丑数是可以被a
或b
或c
整除的 正整数 。思路:一个区间的可以被a/b/c除的个数为
![]()
class Solution { public int nthUglyNumber(int n, int a, int b, int c) { long ab = zuixiaogongbei(a, b); long bc = zuixiaogongbei(b, c); long ac = zuixiaogongbei(a, c); long abc = zuixiaogongbei(a, bc); long min = Math.min(a, Math.min(b, c)); long l = 0; long r = min * n; while (l <= r) { long mid = (l + r) >> 1; long cnt = mid / a + mid / b + mid / c - mid / ab - mid / bc - mid / ac + mid / abc; if (cnt == n) { if (mid % a == 0 || mid % b == 0 || mid % c == 0) return (int) mid; else r = mid - 1; } else if (cnt > n) r = mid - 1; else l = mid + 1; } return (int) l; } public long zuixiaogongbei(long a, long b) { return (b / gcd(a, b)) * a; } public int gcd(long x, long y) { return y == 0 ? (int) x : gcd(y, x % y); } }
3,等差数列
413,等差数列划分
题目:如果一个数列 至少有三个元素 ,并且任意两个相邻元素之差相同,则称该数列为等差数列。例如,[1,3,5,7,9]、[7,7,7,7] 和 [3,-1,-5,-9] 都是等差数列。给你一个整数数组 nums ,返回数组 nums 中所有为等差数组的 子数组 个数。子数组 是数组中的一个连续序列。
class Solution { public int numberOfArithmeticSlices(int[] nums) { int n = nums.length; if (n == 1) { return 0; } int d = nums[0] - nums[1], t = 0; int ans = 0; // 因为等差数列的长度至少为 3,所以可以从 i=2 开始枚举 for (int i = 2; i < n; ++i) { if (nums[i - 1] - nums[i] == d) { ++t; } else { d = nums[i - 1] - nums[i]; t = 0; } ans += t; } return ans; } }
441,排列硬币
题目:你总共有 n 枚硬币,并计划将它们按阶梯状排列。对于一个由 k 行组成的阶梯,其第 i 行必须正好有 i 枚硬币。阶梯的最后一行 可能 是不完整的。给你一个数字 n ,计算并返回可形成 完整阶梯行 的总行数。
思路:
class Solution { public int arrangeCoins(int n) { return (int) (Math.sqrt(2 * (long) n + 0.25)-0.5); } }
1502,判断能否形成等差数列
题目:给你一个数字数组 arr 。如果一个数列中,任意相邻两项的差总等于同一个常数,那么这个数列就称为 等差数列 。如果可以重新排列数组形成等差数列,请返回 true ;否则,返回 false 。
class Solution { public boolean canMakeArithmeticProgression(int[] arr) { Arrays.sort(arr); int temp = arr[1]-arr[0]; for (int i = 1; i < arr.length-1; i++) { if (arr[i+1]-arr[i]!=temp){ return false; } } return true; } }
1630,等差子数列
题目:给你一个由 n 个整数组成的数组 nums,和两个由 m 个整数组成的数组 l 和 r,后两个数组表示 m 组范围查询,其中第 i 个查询对应范围 [l[i], r[i]] 。所有数组的下标都是 从 0 开始 的。返回 boolean 元素构成的答案列表 answer 。如果子数组 nums[l[i]], nums[l[i]+1], ... , nums[r[i]] 可以 重新排列 形成 等差数列 ,answer[i] 的值就是 true;否则answer[i] 的值就是 false 。
class Solution { public List<Boolean> checkArithmeticSubarrays(int[] nums, int[] l, int[] r) { ArrayList result = new ArrayList(); int m = l.length; for (int i = 0; i < m; i++) { int left = l[i]; int right = r[i]; int[] temp = new int[right - left + 1]; for (int j = left; j <= right; j++) { temp[j - left] = nums[j]; } Arrays.sort(temp); result.add(canMakeArithmeticProgression(temp)); } return result; } public boolean canMakeArithmeticProgression(int[] arr) { Arrays.sort(arr); int temp = arr[1] - arr[0]; for (int i = 1; i < arr.length - 1; i++) { if (arr[i + 1] - arr[i] != temp) { return false; } } return true; } }
4,规律数列
233,数字1,2的个数
题目:给定一个整数
n
,计算所有小于等于n
的非负整数中数字1
出现的个数。class Solution { public int countDigitOne(int n) { long ans = 0; long count; long rest; for (long i = 1; i <= n; i *= 10) { count = (n / (i * 10)) * i; // 分别统计个位的1 十位 百位..... //111 个位共计11个1, '1', 1'1', 2'1', 3'1', 4'1', 5'1', 6'1', 7'1', 8'1', 9'1', 10'1' //只统计到小于等于110 多出为余数 //111 十位有10个1, '1'0, '1'1, '1'2, '1'3, '1'4, '1'5, '1'6, '1'7, '1'8, '1'9 rest = Math.min(Math.max(n % (i * 10) - (i - 1), 0), i); // 1 0 // 10 9 //100 99 //下面举例100和111的余数 // 如果为负数则取余为0 // 100 个位为0 无余数 // 111 个位为1 有一个余数 111 第三位 11‘1’ // 100 十位为0 无余数 // 111 十位为1 有两个余数 110 111 中间位置1‘1’0 和1‘1’1 // 100 百位为1 有一个余数 100 第一位‘1’00 // 111 百位为1 有十二个余数 100....... 111 第一位 '1'00 .......... '1'11 ans += (count + rest); } return (int)ans; } }
题目:编写一个方法,计算从 0 到 n (含 n) 中数字 2 出现的次数。
思路:
- 当某一位小于2时,该位上数字2出现的次数等于高位数字乘以当前位的权重(比如说,对于个位来说,权重是1;对于十位来说,权重是10)。
- 当某一位等于2时,该位上数字2出现的次数等于高位数字乘以当前位的权重,再加上低位数字加1。
- 当某一位大于2时,该位上数字2出现的次数等于(高位数字加1)乘以当前位的权重。
class Solution { public int numberOf2sInRange(int n) { int count = 0; int weight = 1; while (n >= weight) { int high = n / (weight * 10); int current = (n / weight) % 10; int low = n % weight; if (current < 2) { count += high * weight; } else if (current == 2) { count += high * weight + low + 1; } else { count += (high + 1) * weight; } weight *= 10; } return count; } }
400,第N位数字
题目:给你一个整数
n
,请你在无限的整数序列[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, ...]
中找出并返回第n
位上的数字。/* 数字范围 数量 位数 占多少位 1-9 9 1 9 10-99 90 2 180 100-999 900 3 2700 1000-9999 9000 4 36000 ... 例如 2901 = 9 + 180 + 2700 + 12 即一定是4位数,第12位 n = 12; 数据为 = 1000 + (12 - 1)/ 4 = 1000 + 2 = 1002 定位1002中的位置 = (n - 1) % 4 = 3 s.charAt(3) = 2; */ class Solution { public int findNthDigit(int n) { int digit = 1; // n所在数字的位数 long start = 1; // 数字范围开始的第一个数 long count = 9; // 占多少位 while(n > count){ n -= count; digit++; start *= 10; count = digit * start * 9; } long num = start + (n - 1) / digit; return Long.toString(num).charAt((n - 1) % digit) - '0'; } }
5,函数曲线
64,交点
题目:给定两条线段(表示为起点
start = {X1, Y1}
和终点end = {X2, Y2}
),如果它们有交点,请计算其交点,没有交点则返回空值。要求浮点型误差不超过10^-6
。若有多个交点(线段重叠)则返回 X 值最小的点,X 坐标相同则返回 Y 值最小的点。class Solution { public double[] intersection(int[] start1, int[] end1, int[] start2, int[] end2) { //求两线段的最大点和最小点 int xmin1 = start1[0] < end1[0] ? start1[0] : end1[0]; int ymin1 = start1[1] < end1[1] ? start1[1] : end1[1]; int xmin2 = start2[0] < end2[0] ? start2[0] : end2[0]; int ymin2 = start2[1] < end2[1] ? start2[1] : end2[1]; int xmax1 = start1[0] > end1[0] ? start1[0] : end1[0]; int ymax1 = start1[1] > end1[1] ? start1[1] : end1[1]; int xmax2 = start2[0] > end2[0] ? start2[0] : end2[0]; int ymax2 = start2[1] > end2[1] ? start2[1] : end2[1]; double x = 0; double y = 0; //如果两点在直线的同一侧,代入方程同号 int f11 = fangcheng(start2[0],start2[1],start1[0],start1[1],end1[0],end1[1]); int f12 = fangcheng(end2[0],end2[1],start1[0],start1[1],end1[0],end1[1]); int f21 = fangcheng(start1[0],start1[1],start2[0],start2[1],end2[0],end2[1]); int f22 = fangcheng(end1[0],end1[1],start2[0],start2[1],end2[0],end2[1]); //两点在直线的同侧,没有交点 if (f11 * f12 > 0 || f21*f22 > 0){ return new double[0]; }else if(f11 == f12 && f12 == f21 && f21 == f22){//四点共线 // 没有交叉排列 if (xmax1 < xmin2 || xmax2 < xmin1){ return new double[0]; }else if(xmax1 == xmin1 && xmin1 == xmax2 && xmax2 == xmin2){//垂直的线,判断y //没有交叉 if (ymax1 < ymin2 || ymax2 < ymin1){ return new double[0]; }else{ //取两个条线的小值中最大的,得交叉点小点 x = xmax1; y = ymin1 > ymin2 ? ymin1 : ymin2; return new double[]{x,y}; } }else { //取两个条线的小值中最大的,得交叉点小点 x = xmin1 > xmin2 ? xmin1 : xmin2; if (start1[0] == x){ y = start1[1]; }else if(end1[0] == x){ y = end1[1]; }else if (start2[0] == x){ y = start2[1]; }else { y = end2[1]; } return new double[]{x,y}; } }else{ // 线段1垂直 if (start1[0] == end1[0]){ x = start1[0]; double xue2 = 1.0*(start2[1] - end2[1])/(start2[0] - end2[0]); double b2 = end2[1] - xue2 * end2[0]; y = xue2 * x + b2; return new double[]{x,y}; }else if (start2[0] == end2[0]){//线段2垂直 x = start2[0]; double xue1 = 1.0*(start1[1] - end1[1])/(start1[0] - end1[0]); double b1 = end1[1] - xue1 * end2[0]; y = xue1 * x + b1; return new double[]{x,y}; }else {//通用情况,线段1和线段2都不垂直,计算斜率、常量值,y=a*x+b double xue1 = 1.0*(start1[1] - end1[1])/(start1[0] - end1[0]);//斜率1 double xue2 = 1.0*(start2[1] - end2[1])/(start2[0] - end2[0]);//斜率2 double b1 = end1[1] - xue1 * end1[0];//常量b1 double b2 = end2[1] - xue2 * end2[0];//常量b2 x = (b2 - b1)/(xue1 - xue2); y = xue1 * x + b1; return new double[]{x,y}; } } } //验证两点是否在另一条直线的同一侧,同一侧同号,不同侧异号 private int fangcheng(int x,int y,int x0,int y0,int x1,int y1){ return (x-x0)*(y1-y0) - (x1-x0)*(y-y0); } }
73,平方正方形
题目:给定两个正方形及一个二维平面。请找出将这两个正方形分割成两半的一条直线。假设正方形顶边和底边与 x 轴平行。
每个正方形的数据
square
包含3个数值,正方形的左下顶点坐标[X,Y] = [square[0],square[1]]
,以及正方形的边长square[2]
。所求直线穿过两个正方形会形成4个交点,请返回4个交点形成线段的两端点坐标(两个端点即为4个交点中距离最远的2个点,这2个点所连成的线段一定会穿过另外2个交点)。2个端点坐标[X1,Y1]
和[X2,Y2]
的返回格式为{X1,Y1,X2,Y2}
,要求若X1 != X2
,需保证X1 < X2
,否则需保证Y1 <= Y2
。若同时有多条直线满足要求,则选择斜率最大的一条计算并返回(与Y轴平行的直线视为斜率无穷大)。
class Solution { public double[] cutSquares(int[] square1, int[] square2) { double x1 = square1[0] + square1[2] / 2.0; double y1 = square1[1] + square1[2] / 2.0; double x2 = square2[0] + square2[2] / 2.0; double y2 = square2[1] + square2[2] / 2.0; if (x1 == x2) { double temp1 = square1[1] + square1[2]; double temp2 = square2[1] + square2[2]; return new double[]{x1, Math.min(square1[1], square2[1]), x1, Math.max(temp2, temp1)}; } double[] result = new double[4]; double k = (y2 - y1) / (x2 - x1); double b = y2 - k * x2; if(Math.abs(k) >= 1){ // 直线穿过两个正方形的上下边 result[1] = Math.min(square1[1], square2[1]); // 先求出y,选两个正方形中靠下的底边 result[0] = (result[1]-b)/k; result[3] = Math.max(square1[1]+square1[2], square2[1]+square2[2]); result[2] = (result[3]-b)/k; }else{ result[0] = Math.min(square1[0], square2[0]); result[1] = k*result[0]+b; result[2] = Math.max(square1[0]+square1[2], square2[0]+square2[2]); result[3] = k*result[2]+b; } if(result[0] > result[2]){ swap(result, 0, 2); swap(result, 1, 3); } return result; } public void swap(double[] res, int x, int y){ double temp = res[x]; res[x] = res[y]; res[y] = temp; } }