目录
-
- 1.至少是其他数字两倍的最大数
- 2.二进制表示中质数个计算置位
- [3. 托普利茨矩阵](#3. 托普利茨矩阵)
- [4. 宝石与石头](#4. 宝石与石头)
- [5. 网格图中机器人回家的最小代价](#5. 网格图中机器人回家的最小代价)
1.至少是其他数字两倍的最大数
给你一个整数数组 nums ,其中总是存在 唯一的 一个最大整数 。
请你找出数组中的最大元素并检查它是否 至少是数组中每个其他数字的两倍 。如果是,则返回 最大元素的下标 ,否则返回 -1 。
示例 1:
输入:nums = [3,6,1,0]
输出:1
解释:6 是最大的整数,对于数组中的其他整数,6 至少是数组中其他元素的两倍。6 的下标是 1 ,所以返回 1 。
思路
只要找到最大数和第二大数即可,只要最大数比第二大数大两倍即可
java
class Solution {
public int dominantIndex(int[] nums) {
int fMax=0,sMax=0;
int fIndex=0;
for(int i=0;i<nums.length;i++){
if(nums[i]>fMax){
sMax = fMax;
fMax = nums[i];
fIndex = i;
}else if(nums[i]>sMax){
sMax = nums[i];
}
}
return fMax>=sMax*2?fIndex:-1;
}
}
时间复杂度: O(N)
空间复杂度: O(1)
2.二进制表示中质数个计算置位
给你两个整数 left 和 right ,在闭区间 [left, right] 范围内,统计并返回 计算置位位数为质数 的整数个数。
计算置位位数 就是二进制表示中 1 的个数。
例如, 21 的二进制表示 10101 有 3 个计算置位。
示例 1:
输入:left = 6, right = 10
输出:4
解释:
6 -> 110 (2 个计算置位,2 是质数)
7 -> 111 (3 个计算置位,3 是质数)
9 -> 1001 (2 个计算置位,2 是质数)
10-> 1010 (2 个计算置位,2 是质数)
共计 4 个计算置位为质数的数字。
提示:
1 <= left <= right <= 10^6
0 <= right - left <= 10^4
思路
这里提示指出数字范围在10^6以内,二进制中1的个数2,3,5,7,11,13,17,19这些个数为质数,因此可以用32位的有符号数来标记这些数,将这些位置置为1,则得到32位有符号数665772,只要与该数按位与不为零,则表示为质数,统计即可
java
class Solution {
//数字n用二进制第n位为1来标记,相当于32位的bitmap
//0000_0000_0000_0101_0001_0100_0101_0110=665772
//2对应0010
//3对应0100
//5对应0001_0000
//以此类推19对应0100_0000_0000_0000_0000,二进制第19位为1
public int countPrimeSetBits(int left, int right) {
int count = 0;
int mask = 665772;
while(left<=right){
int n = left;
int cnts = 0;
//每循环一次,消除最右侧的1
//复习位运算:x&(-x) lowBit运算,找到最低位的1
while(n>0){
//位运算:消除最低位的1
n&=(n-1);
cnts++;
}
if(((1<<cnts)&mask)!=0){
count++;
}
left++;
}
return count;
}
}
时间复杂度: O(right-left)
空间复杂度: O(1)
3. 托普利茨矩阵
给你一个 m x n 的矩阵 matrix 。如果这个矩阵是托普利茨矩阵,返回 true ;否则,返回 false 。
如果矩阵上每一条由左上到右下的对角线上的元素都相同,那么这个矩阵是托普利茨矩阵 。
示例 1:
输入:matrix = [[1,2,3,4],[5,1,2,3],[9,5,1,2]]
输出:true
解释:
在上述矩阵中, 其对角线为:
"[9]", "[5, 5]", "[1, 1, 1]", "[2, 2, 2]", "[3, 3]", "[4]"。
各条对角线上的所有元素均相同, 因此答案是True 。
思路
开始的思路是验证首行和首列,后来查看题解发现小技巧是,每次验证相邻行即可
java
class Solution {
public boolean isToeplitzMatrix(int[][] matrix) {
int m=matrix.length,n=matrix[0].length;
for(int i=0;i<m-1;i++){
for(int j=0;j<n-1;j++){
if(matrix[i][j]!=matrix[i+1][j+1]){
return false;
}
}
}
return true;
}
}
时间复杂度: O(n*m) 遍历矩阵即可
空间复杂度: O(1)
4. 宝石与石头
给你一个字符串 jewels 代表石头中宝石的类型,另有一个字符串 stones 代表你拥有的石头。 stones 中每个字符代表了一种你拥有的石头的类型,你想知道你拥有的石头中有多少是宝石。
字母区分大小写,因此 "a" 和 "A" 是不同类型的石头。
示例 1:
输入:jewels = "aA", stones = "aAAbbbb"
输出:3
示例 2:
输入:jewels = "z", stones = "ZZ"
输出:0
思路
分别统计a-zA-Z是否为宝石,有一种bitmap的思路是用64位long型来标记a-zA-Z,大写字母二进制的低 6 位是从 000001 开始的(对应大写字母 A),一直到 011010(对应大写字母 Z)。
小写字母二进制的低 6 位是从 100001 开始的(对应小写字母 a),一直到 111010(对应小写字母 z),即十进制的 58。因此可以用低6位来区分大小写,每个数字对应一个字母
java
class Solution {
public int numJewelsInStones(String jewels, String stones) {
long mask = 0;
for(char c:jewels.toCharArray()){
//将字符与63与得到字符低6位对应的数字,将64位二进制数对应位置置为1
mask |= 1L<<(c&63);
}
int cnt = 0;
for(char c:stones.toCharArray()){
//判断该字符对应mask位置是否为1,为1则是宝石
if((mask&(1L<<(c&63)))!=0){
cnt++;
}
}
return cnt;
}
}
时间复杂度: O(m+n),m和n分别为两字符串长度
空间复杂度: O(1)
5. 网格图中机器人回家的最小代价
给你一个 m x n 的网格图,其中 (0, 0) 是最左上角的格子,(m - 1, n - 1) 是最右下角的格子。给你一个整数数组 startPos ,startPos = [startrow, startcol] 表示 初始 有一个 机器人 在格子 (startrow, startcol) 处。同时给你一个整数数组 homePos ,homePos = [homerow, homecol] 表示机器人的 家 在格子 (homerow, homecol) 处。
机器人需要回家。每一步它可以往四个方向移动:上,下,左,右,同时机器人不能移出边界。每一步移动都有一定代价。再给你两个下标从 0 开始的额整数数组:长度为 m 的数组 rowCosts 和长度为 n 的数组 colCosts 。
如果机器人往 上 或者往 下 移动到第 r 行 的格子,那么代价为 rowCosts[r] 。
如果机器人往 左 或者往 右 移动到第 c 列 的格子,那么代价为 colCosts[c] 。
请你返回机器人回家需要的 最小总代价 。
示例 1:
输入:startPos = [1, 0], homePos = [2, 3], rowCosts = [5, 4, 3], colCosts = [8, 2, 6, 7]
输出:18
解释:一个最优路径为:
从 (1, 0) 开始
-> 往下走到 (2, 0) 。代价为 rowCosts[2] = 3 。
-> 往右走到 (2, 1) 。代价为 colCosts[1] = 2 。
-> 往右走到 (2, 2) 。代价为 colCosts[2] = 6 。
-> 往右走到 (2, 3) 。代价为 colCosts[3] = 7 。
总代价为 3 + 2 + 6 + 7 = 18
思路
只要移动两点间的行差和列差即可
java
class Solution {
public int minCost(int[] startPos, int[] homePos, int[] rowCosts, int[] colCosts) {
//若在家,代价为0
if(startPos[0]==homePos[0]&&startPos[1]==homePos[1]){
return 0;
}
int i = startPos[0]<=homePos[0]?1:-1;
int j = startPos[1]<=homePos[1]?1:-1;
int x = startPos[0];
int y = startPos[1];
int exp = 0;
while(x!=homePos[0]){
x+=i;
exp += rowCosts[x];
}
while(y!=homePos[1]){
y+=j;
exp += colCosts[y];
}
return exp;
}
}
时间复杂度: O(m+n) m和n分别是行数和列数
空间复杂度: O(1)