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);
}
}
Q16.4 井字游戏
设计一个算法,判断玩家是否赢了井字游戏。输入是一个 N x N 的数组棋盘,由字符" ",“X"和"O"组成,其中字符” "代表一个空位。
以下是井字游戏的规则:
玩家轮流将字符放入空位(" ")中。
第一个玩家总是放字符"O",且第二个玩家总是放字符"X"。
"X"和"O"只允许放置在空位中,不允许对已放有字符的位置进行填充。
当有N个相同(且非空)的字符填充任何行、列或对角线时,游戏结束,对应该字符的玩家获胜。
当所有位置非空时,也算为游戏结束。
如果游戏结束,玩家不允许再放置字符。
如果游戏存在获胜者,就返回该游戏的获胜者使用的字符(“X"或"O”);如果游戏以平局结束,则返回 “Draw”;如果仍会有行动(游戏未结束),则返回 “Pending”。
示例 1:
输入: board = [“O X”," XO",“X O”]
输出: “X”
示例 2:
输入: board = [“OOX”,“XXO”,“OXO”]
输出: “Draw”
解释: 没有玩家获胜且不存在空位
示例 3:
输入: board = [“OOX”,“XXO”,"OX "]
输出: “Pending”
解释: 没有玩家获胜且仍存在空位
提示:
1 <= board.length == board[i].length <= 100
输入一定遵循井字棋规则
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/tic-tac-toe-lcci
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
class Solution {
// 井字游戏
public String tictactoe(String[] board) {
int n = board.length;
char[][] grid = new char[n][n];
for (int i = 0; i < n; i++) {
grid[i] = board[i].toCharArray();
}
int empty = 0;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (grid[i][j] == ’ ') empty++;
}
}
if (empty > 0) {
if (check(grid, ‘X’)) return “X”;
if (check(grid, ‘O’)) return “O”;
return “Pending”;
}
if (check(grid, ‘X’)) return “X”;
if (check(grid, ‘O’)) return “O”;
return “Draw”;
}
private boolean check(char[][] grid, char c) {
int n = grid.length;
// 检查行
for (int row = 0; row < n; row++) {
int col;
for (col = 0; col < n; col++) {
if (grid[row][col] != c) break;
}
if (col >= n) return true;
}
// 检查列
for (int col = 0; col < n; col++) {
int row;
for (row = 0; row < n; row++) {
if (grid[row][col] != c) break;
}
if (row >= n) return true;
}
// 主对角线
int i;
for (i = 0; i < n; i++) {
if (grid[i][i] != c) break;
}
if (i >= n) return true;
// 副对角线
i = 0;
for (; i < n; i++) {
if (grid[i][n - 1 - i] != c) break;
}
return i >= n;
}
}
Q16.5 阶乘尾数
设计一个算法,算出 n 阶乘有多少个尾随零。
示例 1:
输入: 3
输出: 0
解释: 3! = 6, 尾数中没有零。
示例 2:
输入: 5
输出: 1
解释: 5! = 120, 尾数中有 1 个零.
说明: 你算法的时间复杂度应为 O(log n) 。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/factorial-zeros-lcci
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
class Solution {
public int trailingZeroes(int n) {
/*
0 是由 *10 得到的,而 10 是由 2 * 5 得到的
因此我们求 n! 过程中存在多少个 2 * 5
因为 2 的个数必定比 5 的个数多,因此我们只求 5 的个数
如果直接一个一个遍历,即
for(int i = 5; i <= n; i++){
int temp = i;
while(temp % 5 == 0){
count++;
temp /= 5;
}
}
那么 n 过大时,从 1 遍历到 n, 那么会超时,因此我们修改下规律
n! = 1 * 2 * 3 * 4 * (1 * 5) * … * (2 * 5) * … * (3 * 5) …
我们发现,
每隔 5 个数就会出现 一个 5,因此我们只需要通过 n / 5 来计算存在存在多少个 5 个数,那么就对应的存在多少个 5
但是,我们也会发现
每隔 25 个数会出现 一个 25, 而 25 存在 两个 5,我们上面只计算了 25 的一个 5,因此我们需要 n / 25 来计算存在多少个 25,加上它遗漏的 5
同时,我们还会发现
每隔 125 个数会出现一个 125,而 125 存在 三个 5,我们上面只计算了 125 的两个 5,因此我们需要 n / 125 来计算存在多少个 125,加上它遗漏的 5
…
因此我们 count = n / 5 + n / 25 + n / 125 + …
最终分母可能过大溢出,上面的式子可以进行转换
count = n / 5 + n / 5 / 5 + n / 5 / 5 / 5 + …
因此,我们这样进行循环
n /= 5;
count += n;
这样,第一次加上的就是 每隔 5 个数的 5 的个数,第二次加上的就是 每隔 25 个数的 5 的个数 …
*/
int count = 0;
while(n >= 5){
n /= 5;
count += n;
}
return count;
}
}
Q16.6 最小差
给定两个整数数组a和b,计算具有最小差绝对值的一对数值(每个数组中取一个值),并返回该对数值的差
示例:
输入:{1, 3, 15, 11, 2}, {23, 127, 235, 19, 8}
输出: 3,即数值对(11, 8)
提示:
1 <= a.length, b.length <= 100000
-2147483648 <= a[i], b[i] <= 2147483647
正确结果在区间[-2147483648, 2147483647]内
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/smallest-difference-lcci
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
class Solution {
public int smallestDifference(int[] a, int[] b) {
/*
对两个数组进行排序
双指针
int diff = a[i] - b[j]
如果 diff < 0 ,表示 a[i] 小于 b[j] ,a 尽可能接近 b,那么 i++
如果 diff > 0 ,表示 a[i] 大于 b[j] ,b 尽可能接近 a,那么 j++
特殊情况:
a = {1,2,3,4,5}
b = {6,7,8,9,10}
如果 a 数组最大值比 b 数组最小值还小,那么 a 数组 i 会一直右移,直到到达边界 break
*/
int alen = a.length;
int blen = b.length;
Arrays.sort(a);
Arrays.sort(b);
int minVal = Integer.MAX_VALUE;
int i = 0;
int j = 0;
while(i < alen && j < blen){
//使用 long,防止 -2147483648 转正数后还是 -2147483648
long diff = a[i] - b[j];
minVal = (int)Math.min(Math.abs(diff), minVal);
if(diff < 0){
i++;
}else{
j++;
}
}
return minVal;
}
}
Q16.7 最大数值
编写一个方法,找出两个数字
a
和b
中最大的那一个。不得使用if-else或其他比较运算符。
示例:
输入: a = 1, b = 2
输出: 2
class Solution {
public int maximum(int a, int b) {
long dif = (long)a - (long)b;
int k = (int)(dif >>> 63);
return a*(k^1) + b*k;
}
}
Q16.8 整数的英语表示
给定一个整数,打印该整数的英文描述。
示例 1:
输入: 123
输出: “One Hundred Twenty Three”
示例 2:
输入: 12345
输出: “Twelve Thousand Three Hundred Forty Five”
示例 3:
输入: 1234567
输出: “One Million Two Hundred Thirty Four Thousand Five Hundred Sixty Seven”
示例 4:
输入: 1234567891
输出: “One Billion Two Hundred Thirty Four Million Five Hundred Sixty Seven Thousand Eight Hundred Ninety One”
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/english-int-lcci
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
/*
*@v7fgg
*执行用时 :17 ms, 在所有 Java 提交中击败了27.86%的用户
*内存消耗 :39.8 MB, 在所有 Java 提交中击败了100.00%的户
*2020年6月18日 22:24
*/
class Solution {
public String numberToWords(int num) {
//考虑特殊情况的0
if(num==0){return “Zero”;}
String ans=“”;
//原数字在后面还要用到,因此复制一份,这里只需要考虑绝对值
int m=Math.abs(num);
int yi=m%1000;//1000以内的值,也就是后三位
int qian=m/1000%1000;//多少千thousand
int baiwan=m/1000000%1000;//多少百万million
int shiyi=m/1000000000;//多少十亿billion
if(yi>0){
ans=in1000(yi);
}
if(qian>0){
ans=in1000(qian)+" Thousand "+ans;
}
if(baiwan>0){
ans=in1000(baiwan)+" Million "+ans;
}
if(shiyi>0){
ans=in1000(shiyi)+" Billion "+ans;
}
//考虑负数的情况
if(num<0){ans="Negative "+ans;}
return ans.trim();
}
public String in1000(int a){
//此函数是把一个1000以内的数字变成字符串
String shuzi1[]=new String[]{“”,“One”,“Two”,“Three”,“Four”,“Five”,“Six”,“Seven”,“Eight”,“Nine”,“Ten”,“Eleven”,“Twelve”,“Thirteen”,“Fourteen”,“Fifteen”,“Sixteen”,“Seventeen”,“Eighteen”,“Nineteen”};
String shuzi2[]=new String[]{“”,“Ten”,“Twenty”,“Thirty”,“Forty”,“Fifty”,“Sixty”,“Seventy”,“Eighty”,“Ninety”};
String r=“”;
if(a%100<20){
r=shuzi1[a%100];
a/=100;
}
else{
r=shuzi1[a%10];
a/=10;
if(a>0){
//要去掉空格,因为会出现比如:3000000 thirty thousand
r=(shuzi2[a%10]+" "+r).trim();
a/=10;
}
}
if(a>0){
//去空格是因为会出现比如:100000 one hundred thousand
r=(shuzi1[a]+" Hundred "+r).trim();
}
return r;
}
}
Q16.9 运算
请实现整数数字的乘法、减法和除法运算,运算结果均为整数数字,程序中只允许使用加法运算符和逻辑运算符,允许程序中出现正负常数,不允许使用位运算。
你的实现应该支持如下操作:
Operations() 构造函数
minus(a, b) 减法,返回a - b
multiply(a, b) 乘法,返回a * b
divide(a, b) 除法,返回a / b
示例:
Operations operations = new Operations();
operations.minus(1, 2); //返回-1
operations.multiply(3, 4); //返回12
operations.divide(5, -2); //返回-2
提示:
你可以假设函数输入一定是有效的,例如不会出现除法分母为0的情况
单个用例的函数调用次数不会超过1000次
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/operations-lcci
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
import java.math.BigInteger;
class Operations {
public Operations() {
}
public int minus(int a, int b) {
return BigInteger.valueOf(a).subtract(BigInteger.valueOf(b)).intValue();
}
public int multiply(int a, int b) {
return BigInteger.valueOf(a).multiply(BigInteger.valueOf(b)).intValue();
}
public int divide(int a, int b) {
最后
今天关于面试的分享就到这里,还是那句话,有些东西你不仅要懂,而且要能够很好地表达出来,能够让面试官认可你的理解,例如Handler机制,这个是面试必问之题。有些晦涩的点,或许它只活在面试当中,实际工作当中你压根不会用到它,但是你要知道它是什么东西。
最后在这里小编分享一份自己收录整理上述技术体系图相关的几十套腾讯、头条、阿里、美团等公司2021年的面试题,把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节,由于篇幅有限,这里以图片的形式给大家展示一部分。
还有 高级架构技术进阶脑图、Android开发面试专题资料,高级进阶架构资料 帮助大家学习提升进阶,也节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习。
【算法合集】
【延伸Android必备知识点】
【Android部分高级架构视频学习资源】
Android精讲视频领取学习后更加是如虎添翼!进军BATJ大厂等(备战)!现在都说互联网寒冬,其实无非就是你上错了车,且穿的少(技能),要是你上对车,自身技术能力够强,公司换掉的代价大,怎么可能会被裁掉,都是淘汰末端的业务Curd而已!现如今市场上初级程序员泛滥,这套教程针对Android开发工程师1-6年的人员、正处于瓶颈期,想要年后突破自己涨薪的,进阶Android中高级、架构师对你更是如鱼得水,赶快领取吧!
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门,即可获取!
话,有些东西你不仅要懂,而且要能够很好地表达出来,能够让面试官认可你的理解,例如Handler机制,这个是面试必问之题。有些晦涩的点,或许它只活在面试当中,实际工作当中你压根不会用到它,但是你要知道它是什么东西。
最后在这里小编分享一份自己收录整理上述技术体系图相关的几十套腾讯、头条、阿里、美团等公司2021年的面试题,把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节,由于篇幅有限,这里以图片的形式给大家展示一部分。
还有 高级架构技术进阶脑图、Android开发面试专题资料,高级进阶架构资料 帮助大家学习提升进阶,也节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习。
[外链图片转存中…(img-es57ct84-1715849566116)]
【算法合集】
[外链图片转存中…(img-lflBcZKu-1715849566120)]
【延伸Android必备知识点】
[外链图片转存中…(img-zW7Ncd78-1715849566122)]
【Android部分高级架构视频学习资源】
Android精讲视频领取学习后更加是如虎添翼!进军BATJ大厂等(备战)!现在都说互联网寒冬,其实无非就是你上错了车,且穿的少(技能),要是你上对车,自身技术能力够强,公司换掉的代价大,怎么可能会被裁掉,都是淘汰末端的业务Curd而已!现如今市场上初级程序员泛滥,这套教程针对Android开发工程师1-6年的人员、正处于瓶颈期,想要年后突破自己涨薪的,进阶Android中高级、架构师对你更是如鱼得水,赶快领取吧!
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门,即可获取!