目录
1337.矩阵中战斗力最弱的k行🔥🔥
✨✨题目描述
给你一个大小为 m * n 的矩阵 mat,矩阵由若干军人和平民组成,分别用 1 和 0 表示。
请你返回矩阵中战斗力最弱的 k 行的索引,按从最弱到最强排序。
如果第 i 行的军人数量少于第 j 行,或者两行军人数量相同但 i 小于 j,那么我们认为第 i 行的战斗力比第 j 行弱。
军人 总是 排在一行中的靠前位置,也就是说 1 总是出现在 0 之前。
示例 1:
输入:mat =
[[1,1,0,0,0],
[1,1,1,1,0],
[1,0,0,0,0],
[1,1,0,0,0],
[1,1,1,1,1]],
k = 3
输出:[2,0,3]
解释:
每行中的军人数目:
行 0 -> 2
行 1 -> 4
行 2 -> 1
行 3 -> 2
行 4 -> 5
从最弱到最强对这些行排序后得到 [2,0,3,1,4]
🙈🙈思考过程
步骤💨💨
- 首先我们创建一个Node类,里面有两个值,分别为i和count,i为数组的行数,count为此行内1的个数。
- 接着创建一个ci数组,为Node[]类型。
- 接着遍历数组,将他的行下标i和1的个数count存储在ci数组。
- 由于是top-k问题,我们创建一个堆,创建堆时,我们要自己写比较器。
- 接着把ci数组的值添加到堆中,接着我们一次出堆即可。
👨🏻💻👨🏻💻代码
static class Node{
int key;
int val;
public Node(int key,int val) {
this.key = key;
this.val=val;
}
}
public static int[] kWeakestRows(int[][] mat, int k) {
int[] ret=new int[k];
Node[] ci=new Node[mat.length];
for(int i=0;i<mat.length;i++){
int count=0;
for(int j=0;j<mat[0].length;j++){
if(mat[i][j]==1){
count++;
}
}
ci[i]=new Node(i,count);
}
PriorityQueue<Node> queue=new PriorityQueue<>(k,new Comparator<Node>() {
@Override
public int compare(Node o1, Node o2) {
if(o1.val!=o2.val){
return o1.val- o2.val;
}else
return o1.key-o2.key;
}
});
for(Node x:ci){
queue.offer(x);
}
for (int i = 0; i < k; i++) {
ret[i]=queue.poll().key;
}
return ret;
}
注意💨💨
创建比较器时,我们首先比较count也就是Node的val值的大小,如果count相等,我们再用i也就是Node的key值比较。
13.罗马数字转整数🔥🔥
OJ:罗马数字转整数🪢🪢
✨✨题目描述
罗马数字包含以下七种字符: I, V, X, L,C,D 和 M。
字符 数值
I 1
V 5
X 10
L 50
C 100
D 500
M 1000
例如, 罗马数字 2 写做 II ,即为两个并列的 1 。12 写做 XII ,即为 X + II 。 27 写做 XXVII, 即为 XX + V + II 。
通常情况下,罗马数字中小的数字在大的数字的右边。但也存在特例,例如 4 不写做 IIII,而是 IV。数字 1 在数字 5 的左边,所表示的数等于大数 5 减小数 1 得到的数值 4 。同样地,数字 9 表示为 IX。这个特殊的规则只适用于以下六种情况:
I 可以放在 V (5) 和 X (10) 的左边,来表示 4 和 9。
X 可以放在 L (50) 和 C (100) 的左边,来表示 40 和 90。
C 可以放在 D (500) 和 M (1000) 的左边,来表示 400 和 900。
给定一个罗马数字,将其转换成整数。
示例 1: 输入: s = "III" 输出: 3
示例 2: 输入: s = "IV" 输出: 4
示例 3: 输入: s = "IX" 输出: 9
示例 4: 输入: s = "LVIII" 输出: 58 解释: L = 50, V= 5, III = 3.
示例 5: 输入: s = "MCMXCIV" 输出: 1994 解释: M = 1000, CM = 900, XC = 90, IV = 4.
🙉🙉思考过程
👨💻👨💻代码
public int romanToInt(String s) {
HashMap<Character,Integer> map=new HashMap<>();
map.put('I',1);
map.put('V',5);
map.put('X',10);
map.put('L',50);
map.put('C',100);
map.put('D',500);
map.put('M',1000);
int ret=0;
char[] arr=s.toCharArray();
for(int i=0;i<arr.length;i++){
int x=map.get(arr[i]);
if(i<arr.length-1&&x>=map.get(arr[i+1])) ret+=x;
else if(i<arr.length-1&&x<map.get(arr[i+1])) ret-=x;
else ret+=x;
}
return ret;
}
注意💨💨
- 要和i+1项比较,所以比较的条件要满足i<arr.length-1。
- 最后else一定要把最后一个数字加上。
234.回文链表🔥🔥
OJ:回文链表🪢🪢
✨✨题目描述
给你一个单链表的头节点 head
,请你判断该链表是否为回文链表。如果是,返回 true
;否则,返回 false
。
🙉🙉思考过程
步骤💨💨
- 定义快慢指针,f一次走两步,s一次走一步,拿到中间节点,也就是s指向的位置。
- 将f重新指向头结点。
- 将s指向的节点入栈,直到指向空。
- f指向的节点的值与stack出的值比较。
👨🏻💻👨🏻💻代码
public boolean isPalindrome(ListNode head) {
if(head==null){
return true;
}
Stack<Integer> stack=new Stack<>();
ListNode f=head;
ListNode s=head;
while(f!=null&&f.next!=null){
f=f.next.next;
s=s.next;
}
f=head;
while(s!=null){
stack.push(s.val);
s=s.next;
}
while(!stack.empty()){
if(f.val!=stack.pop()){
return false;
}
f=f.next;
}
return true;
}
383.赎金信🔥🔥
OJ:赎金信🪢🪢
✨✨题目描述
给你两个字符串:ransomNote 和 magazine ,判断 ransomNote 能不能由 magazine 里面的字符构成。
如果可以,返回 true ;否则返回 false 。
magazine 中的每个字符只能在 ransomNote 中使用一次。
示例 1:
输入:ransomNote = "a", magazine = "b"
输出:false
示例 2:
输入:ransomNote = "aa", magazine = "ab"
输出:false
示例 3:
输入:ransomNote = "aa", magazine = "aab"
输出:true
🙈🙈思考过程
我们可以定义两个map分别存储字符和他们出现的次数,最后遍历ransomznote看他所在的map1中的字符 map2是否也有,且map2中字符出现的次数需大于map1中的。
👨🏻💻👨🏻💻代码
public boolean canConstruct(String ransomNote, String magazine) {
HashMap<Character,Integer> mapR=new HashMap<>();
HashMap<Character,Integer> mapM=new HashMap<>();
hashPut(mapR,ransomNote);
hashPut(mapM,magazine);
for(char x: ransomNote.toCharArray()){
if(mapM.containsKey(x)&&mapM.get(x)>=mapR.get(x)){
continue;
}else{
return false;
}
}
return true;
}
public void hashPut(HashMap map,String str){
for(char x:str.toCharArray()){
if(map.containsKey(x)){
int val=(int)map.get(x);
map.put(x,val+1);
}else{
map.put(x,1);
}
}
}
HashPut为我们为题目提供的方法,作用是把字符串中的字符和出现次数存在map中。
412.Fizz Buzz🔥🔥
OJ:Fizz Buzz🪢🪢
✨✨题目描述
给你一个整数 n ,找出从 1 到 n 各个整数的 Fizz Buzz 表示,并用字符串数组 answer(下标从 1 开始)返回结果,其中:
answer[i] == "FizzBuzz" 如果 i 同时是 3 和 5 的倍数。
answer[i] == "Fizz" 如果 i 是 3 的倍数。
answer[i] == "Buzz" 如果 i 是 5 的倍数。
answer[i] == i (以字符串形式)如果上述条件全不满足。
示例 1:
输入:n = 3
输出:["1","2","Fizz"]
示例 2:
输入:n = 5
输出:["1","2","Fizz","4","Buzz"]
示例 3:
输入:n = 15
输出:["1","2","Fizz","4","Buzz","Fizz","7","8","Fizz","Buzz","11","Fizz","13","14","FizzBuzz"]
🙈🙈思考过程
直接创建一个ArrayList。
遍历从从1到n,如果只是3的倍数,就add(Fizz)。
如果只是5的倍数,就add(Buzz)。
如果是5和3的公倍数,就add(fizzBuzz)。
都不满足就用String.valueOf(i)将i转换成字符串添加进去。
👨🏻💻👨🏻💻代码
public List<String> fizzBuzz(int n) {
List<String> ret=new ArrayList<>();
for(int i=1;i<n+1;i++){
if(i%3==0&&i%5!=0) ret.add("Fizz");
else if(i%3!=0&&i%5==0) ret.add("Buzz");
else if(i%3==0&&i%5==0) ret.add("FizzBuzz");
else ret.add(String.valueOf(i));
}
return ret;
}
876.链表的中间节点🔥🔥
OJ:链表的中间节点🪢🪢
✨✨题目描述
给定一个头结点为 head 的非空单链表,返回链表的中间结点。
如果有两个中间结点,则返回第二个中间结点。
示例 1:
输入:[1,2,3,4,5]
输出:此列表中的结点 3 (序列化形式:[3,4,5])
返回的结点值为 3 。 (测评系统对该结点序列化表述是 [3,4,5])。
注意,我们返回了一个 ListNode 类型的对象 ans,这样:
ans.val = 3, ans.next.val = 4, ans.next.next.val = 5, 以及 ans.next.next.next = NULL.
示例 2:
输入:[1,2,3,4,5,6]
输出:此列表中的结点 4 (序列化形式:[4,5,6])
由于该列表有两个中间结点,值分别为 3 和 4,我们返回第二个结点。
🙈🙈思考过程
定义快慢指针fast和slow,fast每次走两步,slow每次走一步,fast等于null,或者fast.next等于null,slow刚好走到中间节点,返回slow即可。
👨💻👨💻代码
public ListNode middleNode(ListNode head) {
ListNode fast=head;
ListNode slow=head;
while(fast!=null&&fast.next!=null){
fast=fast.next.next;
slow=slow.next;
}
return slow;
}
1342.将数字变成0的操作次数🔥🔥
✨✨题目描述
给你一个非负整数 num ,请你返回将它变成 0 所需要的步数。 如果当前数字是偶数,你需要把它除以 2 ;否则,减去 1 。
示例 1:
输入:num = 14
输出:6
解释:
步骤 1) 14 是偶数,除以 2 得到 7 。
步骤 2) 7 是奇数,减 1 得到 6 。
步骤 3) 6 是偶数,除以 2 得到 3 。
步骤 4) 3 是奇数,减 1 得到 2 。
步骤 5) 2 是偶数,除以 2 得到 1 。
步骤 6) 1 是奇数,减 1 得到 0 。
示例 2:
输入:num = 8
输出:4
解释:
步骤 1) 8 是偶数,除以 2 得到 4 。
步骤 2) 4 是偶数,除以 2 得到 2 。
步骤 3) 2 是偶数,除以 2 得到 1 。
步骤 4) 1 是奇数,减 1 得到 0 。
🙈🙈思考过程
步骤💨💨
- 定义一个计数器count。
- 遍历数组,如果是偶数,就除2,count++,是奇数,减一,count++。
- 返回count。
👨🏻💻👨🏻💻代码
public int numberOfSteps(int num) {
int count=0;
while(num!=0){
if(num%2==0) num/=2;
else num-=1;
count++;
}
return count;
}
1672.最富有客户的资产总量🔥🔥
OJ:最富有客户的资产总量🪢🪢
✨✨题目描述
给你一个 m x n 的整数网格 accounts ,其中 accounts[i][j] 是第 i 位客户在第 j 家银行托管的资产数量。返回最富有客户所拥有的 资产总量 。
客户的 资产总量 就是他们在各家银行托管的资产数量之和。最富有客户就是 资产总量 最大的客户。
示例 1:
输入:accounts = [[1,2,3],[3,2,1]]
输出:6
解释:
第 1 位客户的资产总量 = 1 + 2 + 3 = 6
第 2 位客户的资产总量 = 3 + 2 + 1 = 6
两位客户都是最富有的,资产总量都是 6 ,所以返回 6 。
示例 2:
输入:accounts = [[1,5],[7,3],[3,5]]
输出:10
解释:
第 1 位客户的资产总量 = 6
第 2 位客户的资产总量 = 10
第 3 位客户的资产总量 = 8
第 2 位客户是最富有的,资产总量是 10。
🙈🙈思考过程
题目很简单,意思就是把每行加起来,然后求所有行和的最大值。
步骤💨💨
- 定义出ret。
- 遍历数组,在第一个循环内定义row存储每行的值。
- 进入二层循环,row累加此时的accounts[i][j]的值。
- 最后比较每行的row,与ret的大小。循环结束,输出ret。
👨🏻💻👨🏻💻代码
public int maximumWealth(int[][] accounts) {
int ret=0;
for(int i=0;i<accounts.length;i++){
int row=0;
for(int j=0;j<accounts[0].length;j++){
row+=accounts[i][j];
}
ret=Math.max(ret,row);
}
return ret;
}