先用toCharArray()分割字符串,记录每个字符占的宽度,如果>100,则行数+1,换行,第二行为上一行最后加大于100的那个字符。依次往下遍历代码如下:
class Solution {
public int[] numberOfLines(int[] widths, String s) {
int[]ans=new int[2];//数组ans[0]表示行数 ans[1]表示每行的宽度
ans[0]=1;
for(char c:s.toCharArray()){
int w=widths[c-'a'];
ans[1]+=w;
if(ans[1]>100){//如果大于100(一行宽度上限为100)
ans[0]++;
ans[1]=w;//最后一个字符无法写在上一行只能记载到下一行
}
}
return ans;
}
}
#27 移除元素
双指针解决,一个指针pos1遍历数组,另一个指针pos2=0指向数组初始位置,如果nums[pos1]!=val 则把pos1的值移到pos2,同时pos2往后。这样就可移除指定val元素。代码如下:
class Solution {
public int removeElement(int[] nums, int val) {
if(nums==null||nums.length==0) return 0;//如果数组为空或0直接返回0
int j=0;//指向初始位置
for(int i=0;i<nums.length;i++){//遍历数组
if(nums[i]!=val){
nums[j]=nums[i];
j++;
}
}
return j;
}
}
思路简单明了:乘法原理进行相加,如果一行有激光器,则和上一行有激光器数量相乘,同时这一行激光器数量=pre,继续往下遍历。代码如下:
class Solution {
public int numberOfBeams(String[] bank) {
int n=bank.length;
int []count=new int[n];//记每一行激光器的数量
for(int i=0;i<n;i++){
String arr=bank[i];
for(int j=0;j<arr.length();j++){
if(arr.charAt(j)=='1') count[i]++;
}
}
int ans=0,pre=0;
for(int i=0;i<n;i++){
if(count[i]>0){//这一行有激光器
ans+=pre*count[i];//上一行激光器数量乘这一行的数量就是产生激光束的数量
pre=count[i];//往下继续
}
}
return ans;
}
}
思路1:用一个集合把数组值放入,如果数组中有需要找的值,则*2(一直到没有为止)输出
class Solution {
public int findFinalValue(int[] nums, int original) {
Set<Integer>set=new HashSet();//创建集合
for(int i=0;i<nums.length;i++){
set.add(nums[i]);//集合中加入值
}
while(set.contains(original)){//如果有original值
original*=2;
}
return original;
}
}
思路2:整体排序,然后从左到右遍历,如果有需要找的值,则*2
class Solution {
public int findFinalValue(int[] nums, int original) {
int n = nums.length;
Arrays.sort(nums);
for (int i = 0;i< n;i++){
if (original == nums[i]){
original *=2;
}
}
return original;
}
}
#2170 使数组变成交替数组的最少操作数 |
交替数组,即偶数项的位置都是同一个数,奇数项的位置也为同一个数,并且奇数项数值不等于偶数项数值,思路很简单:首先用两个哈希表,一个哈希表统计偶数项出现的数字和次数,一个哈希表统计奇数项出现的数字和次数,用一个二维数组记录最大数字和它的数字int[2][2]max,如果奇数最大的数字和偶数最大的数字不等,则最小操作数为数组长度-偶数最大数字次数-奇数最大数字次数。如果奇数最大数字和偶数最大数字相等,则最小操作数为数组长度-Max(奇数最大数字次数+偶数第二大数字次数,偶数最大数字次数+奇数第二大数字次数)代码如下:
class Solution {
public int minimumOperations(int[] nums) {
HashMap<Integer,Integer>even=new HashMap<Integer,Integer>();//偶数表
HashMap<Integer,Integer>odd=new HashMap<Integer,Integer>();//奇数表
int ans=0;
for(int i=0;i<nums.length;i++){
if(i%2==0) even.put(nums[i],even.getOrDefault(nums[i],0)+1);
else odd.put(nums[i],odd.getOrDefault(nums[i],0)+1);
}
int[][]evenMaxAndSubMax=check(even);
int[][]oddMaxAndSubMax=check(odd);
if(evenMaxAndSubMax[0][0]!=oddMaxAndSubMax[0][0]) ans=nums.length-evenMaxAndSubMax[0][1]-oddMaxAndSubMax[0][1];
else ans=nums.length-Math.max(evenMaxAndSubMax[0][1]+oddMaxAndSubMax[1][1],oddMaxAndSubMax[0][1]+evenMaxAndSubMax[1][1]);
return ans;
}
int[][]check(HashMap<Integer,Integer>map){//找位置最多数字和次多数字
int[][]maxAndSubMax=new int[2][2];
for(Integer key:map.keySet()){
int val=map.get(key);
if(val>maxAndSubMax[0][1]){
maxAndSubMax[1][0]=maxAndSubMax[0][0];//次大数字
maxAndSubMax[1][1]=maxAndSubMax[0][1];//次大数字次数
maxAndSubMax[0][0]=key;
maxAndSubMax[0][1]=val;
}else if(val>maxAndSubMax[1][1]){
maxAndSubMax[1][0]=key;
maxAndSubMax[1][1]=val;
}
}
return maxAndSubMax;
}
}
#628 三个数的最大乘积 |
找整形数组中任意三数的最大乘积,有正有负,但是最大值肯定是Max(最大值*第二大值*第三大值,最小值*第二小值*最大值)这样就简单起来了
class Solution {
public int maximumProduct(int[] nums) {
int min1 = Integer.MAX_VALUE, min2 = Integer.MAX_VALUE;
int max1 = Integer.MIN_VALUE, max2 = Integer.MIN_VALUE, max3 = Integer.MIN_VALUE;
for (int x : nums) {
if (x < min1) {
min2 = min1;
min1 = x;
} else if (x < min2) {
min2 = x;
}
if (x > max1) {
max3 = max2;
max2 = max1;
max1 = x;
} else if (x > max2) {
max3 = max2;
max2 = x;
} else if (x > max3) {
max3 = x;
}
}
return Math.max(min1 * min2 * max1, max1 * max2 * max3);
}
}
#414 第三大的数 |
不管数字有多少个,只看数字的值的大小去找第三大的数,用a==null、b==null、c==null一次遍历来填充,如果c最后==null 返回a否则返回c
class Solution {
public int thirdMax(int[] nums) {
Integer a = null, b = null, c = null;
for (int num : nums) {
if (a == null || num > a) {
c = b;
b = a;
a = num;
} else if (a > num && (b == null || num > b)) {
c = b;
b = num;
} else if (b != null && b > num && (c == null || num > c)) {
c = num;
}
}
return c == null ? a : c;
}
}
#154 寻找旋转排序数组中的最小值 II |
原本数组是升序的,进行了多次旋转,我们要找到最小值,如果最小值在中间,那么整体趋势肯定是先升后降再升的(可能中间会有相等的就会一条横线,但总体是前边的),所以遍历数组,设最小值为min=nums[0],从前往后遍历,只要nums[i+1]<=nums[i],那么min=Math.min(min,nums[i+1])
class Solution {
public int findMin(int[] nums) {
int min=nums[0],len=nums.length;
for(int i=1;i<len;i++){
if(nums[i]<=nums[i-1]) min=Math.min(nums[i],min);
}
return min;
}
}
感觉二分法寻找更快,如果pivot=low+(high-low)/2,如果nums[pivot]<nums[high],证明最小值在左边,high=pivot,如果nums[pivot]>nums[high],证明最小值在右边,low=pivot+1,如果nums[pivot]==nums[high],high--往左移减少范围
class Solution {
public int findMin(int[] nums) {
int low = 0;
int high = nums.length - 1;
while (low < high) {
int pivot = low + (high - low) / 2;
if (nums[pivot] < nums[high]) {
high = pivot;
} else if (nums[pivot] > nums[high]) {
low = pivot + 1;
} else {
high -= 1;
}
}
return nums[low];
}
}
写在最后的一点话:
原本是打算把这一周所有刷的题都写一个思路题解的,但本周开始的几天刷的都是随机一题,没有什么内在联系可言,同时几十题让我发现根本写不完题解o(╥﹏╥)o,在今天也让我下定决心,以后每天刷的题都会当天反思汇总起来,在每周末下午发出,一来让自己感觉到有点成就,二来也希望能帮助到别人。