数组—19、32、37、35

19、顺时针打印矩阵

牛客的解法,还不错

简单来说,就是不断地收缩矩阵的边界
定义四个变量代表范围,up、down、left、right

向右走存入整行的值,当存入后,该行再也不会被遍历,代表上边界的 up 加一,同时判断是否和代表下边界的 down 交错
向下走存入整列的值,当存入后,该列再也不会被遍历,代表右边界的 right 减一,同时判断是否和代表左边界的 left 交错
向左走存入整行的值,当存入后,该行再也不会被遍历,代表下边界的 down 减一,同时判断是否和代表上边界的 up 交错
向上走存入整列的值,当存入后,该列再也不会被遍历,代表左边界的 left 加一,同时判断是否和代表右边界的 right 交错

import java.util.ArrayList;
public class Solution {
    public ArrayList<Integer> printMatrix(int [][] matrix) {
        ArrayList<Integer> list = new ArrayList<>();
        if(matrix == null || matrix.length == 0 || matrix[0].length == 0){
            return list;
        }
        int up = 0;
        int down = matrix.length-1;
        int left = 0;
        int right = matrix[0].length-1;
        while(true){
            // 最上面一行
            for(int col=left;col<=right;col++){
                list.add(matrix[up][col]);
            }
            // 向下逼近
            up++;
            // 判断是否越界
            if(up > down){
                break;
            }
            // 最右边一行
            for(int row=up;row<=down;row++){
                list.add(matrix[row][right]);
            }
            // 向左逼近
            right--;
            // 判断是否越界
            if(left > right){
                break;
            }
            // 最下面一行
            for(int col=right;col>=left;col--){
                list.add(matrix[down][col]);
            }
            // 向上逼近
            down--;
            // 判断是否越界
            if(up > down){
                break;
            }
            // 最左边一行
            for(int row=down;row>=up;row--){
                list.add(matrix[row][left]);
            }
            // 向右逼近
            left++;
            // 判断是否越界
            if(left > right){
                break;
            }
        }
        return list;
    }
}

leetcode题解

class Solution {
    public int[] spiralOrder(int[][] matrix) {
        if(matrix.length == 0) return new int[0];
        int l = 0, r = matrix[0].length - 1, t = 0, b = matrix.length - 1, x = 0;
        int[] res = new int[(r + 1) * (b + 1)];
        while(true) {
            for(int i = l; i <= r; i++) res[x++] = matrix[t][i]; // left to right.
            if(++t > b) break;
            for(int i = t; i <= b; i++) res[x++] = matrix[i][r]; // top to bottom.
            if(l > --r) break;
            for(int i = r; i >= l; i--) res[x++] = matrix[b][i]; // right to left.
            if(t > --b) break;
            for(int i = b; i >= t; i--) res[x++] = matrix[i][l]; // bottom to top.
            if(++l > r) break;
        }
        return res;
    }
}

python

class Solution:
    def spiralOrder(self, matrix: List[List[int]]) -> List[int]:
        res = []
        while matrix:
            res += matrix.pop(0)
            matrix = list(zip(*matrix))[::-1]
        return res

32、把数组排成最小的数

本质就是字符串作比较

要注意,java中字符串也可以用compare to作比较

当对字符串进行修改的时候,需要使用 StringBuffer 和 StringBuilder 类。
和 String 类不同的是,StringBuffer 和 StringBuilder 类的对象能够被多次的修改,并且不产生新的未使用对象。

对象本身进行操作,而不是生成新的对象,所以如果需要对字符串进行修改推荐使用StringBuilder

class Solution {
    public String minNumber(int[] nums) {
        String[] strs = new String[nums.length];
        for(int i = 0; i < nums.length; i++)
            strs[i] = String.valueOf(nums[i]);
        Arrays.sort(strs, (x, y) -> (x + y).compareTo(y + x));
        StringBuilder res = new StringBuilder();
        for(String s : strs)
            res.append(s);
        return res.toString();
    }
}

37、数字在排序数组中出现的次数

自己的写法 没通过测试

public class Solution {
    public int GetNumberOfK(int [] array , int k) {
        int low=0;
        int high=array.length-1;
        int mid = low + (high - low) / 2;
        if(array[low]>k || array[high]<k) return 0; 
        while( !(array[low]== k && array[high]== k)){
            if(array[mid]>k) high = mid ;
            if(array[mid]<k) low = mid ;
            if(array[mid]==k && array[low]!=k) low += 1 ;
            if(array[mid]==k && array[high]!=k) high -= 1 ;
            mid = low + (high - low) / 2;
           }
        return high-low+1;
    }
}

官方的二分写法

public class Solution {
    public int GetNumberOfK(int [] array , int k) {
        int length = array.length;
        if(length == 0){
            return 0;
        } //长度为0直接返回0
        int firstK = getFirstK(array, k, 0, length-1);
        int lastK = getLastK(array, k, 0, length-1);
        if(firstK != -1 && lastK != -1){
             return lastK - firstK + 1;
        }
        return 0;
    }
    //递归写法   找到第一个K位置
    private int getFirstK(int [] array , int k, int start, int end){
        if(start > end){
            return -1;
        }
        int mid = (start + end) >> 1;
        if(array[mid] > k){
            return getFirstK(array, k, start, mid-1);//中间大于K,end=mid-1,找左段
        }else if (array[mid] < k){
            return getFirstK(array, k, mid+1, end);//中间小于K,start=mid+1,找右段
        }else if(mid-1 >=0 && array[mid-1] == k){
            return getFirstK(array, k, start, mid-1);//中间在1右边,值为K,找左段
        }else{
            return mid;
        }
    }
    //循环写法  找到最后一个K位置
    private int getLastK(int [] array , int k, int start, int end){
        int length = array.length;
   		int mid = (start + end) >> 1;
        while(start <= end){
            if(array[mid] > k){
                end = mid-1;//中间大于K,end=mid-1,找左段
            }else if(array[mid] < k){
                start = mid+1;//中间小于K,start=mid+1,找右段
            }else if(mid+1 < length && array[mid+1] == k){//中间在最大值左边,值为K,找右段
                start = mid+1;
            }else{
                return mid;
            }
            mid = (start + end) >> 1;
        }
        return -1;
    }
}

35、数组中的逆序对

归并排序

第二种归并排序的方法

public class Solution {
    // 归并排序的思路来做这道题目以实现o(nlogn)的复杂度。
    //归并排序是稳定排序,它也是一种十分高效的排序,能利用完全二叉树特性的排序一般性能都不会太差。
    //java中Arrays.sort()采用了一种名为TimSort的排序算法,就是归并排序的优化版本。
    //从上文的图中可看出,每次合并操作的平均时间复杂度为O(n),而完全二叉树的深度为|log2n|。总的平均时间复杂度为O(nlogn)。
    //而且,归并排序的最好,最坏,平均时间复杂度均为O(nlogn)。
    private int cnt;
        public int InversePairs(int [] array) {
        //在排序前,先建好一个长度等于原数组长度的临时数组,避免递归中频繁开辟空间
        int[] temp=new int[array.length];
        MergeSort(array, 0, array.length-1,temp);
        return cnt;
    }
    
    private void MergeSort(int[] array, int start, int end, int[]temp){
        if(start>=end) return;
        int mid = (start+end)/2;
        
        MergeSort(array, start, mid, temp);//左边 递归
        MergeSort(array, mid+1, end, temp);//右边 递归
        MergeOne(array, start, mid, end,temp);
    }
    private void MergeOne(int[] array, int start, int mid, int end,int[] temp){
        int k=0,i=start,j=mid+1;
        while(i<=mid && j<= end){//当左边起始点小于中间点,右边起始点小于结束点
            //如果前面的元素小于后面的不能构成逆序对
            if(array[i] <= array[j])
                temp[k++] = array[i++];
            //如果前面的元素大于后面的,那么在前面元素之后的元素都能和后面的元素构成逆序对
            else{
                temp[k++] = array[j++];
                
//增加的一行代码,用来统计逆序对个数
                cnt = (cnt + (mid-i+1))%1000000007;
                
            }
        }
        //将左边剩余元素填充进temp中
        while(i<= mid)
            temp[k++] = array[i++];
        //将右序列剩余元素填充进temp中
        while(j<=end)
            temp[k++] = array[j++];
        k=0;
         //将temp中的元素全部拷贝到原数组中
        while(start<=end){
            array[start++] = temp[k++];
        }
    }

}

归并排序的基础上加一行代码

class Solution {
    //全局变量
    private int count; 
    public int reversePairs(int[] nums) {
         count = 0;      
         merge(nums,0,nums.length-1);
         return count;
    }

    public void merge (int[] nums, int left, int right) {

        if (left < right) {
            int mid = left + ((right - left) >> 1);
            merge(nums,left,mid);
            merge(nums,mid+1,right);
            mergeSort(nums,left,mid,right);
        }

    }

    public void mergeSort(int[] nums, int left, int mid, int right) {

         int[] temparr = new int[right-left+1];
         int index = 0;
         int temp1 = left, temp2 = mid+1;

         while (temp1 <= mid && temp2 <= right) {
             
             if (nums[temp1] <= nums[temp2]) {
                 temparr[index++] = nums[temp1++];
             } else {
                 //增加的一行代码,用来统计逆序对个数
                 count += (mid - temp1 + 1);
                 temparr[index++] = nums[temp2++];
             }
         }
         
         if (temp1 <= mid) System.arraycopy(nums,temp1,temparr,index,mid-temp1+1);
         if (temp2 <= right) System.arraycopy(nums,temp2,temparr,index,right-temp2+1);
         System.arraycopy(temparr,0,nums,left,right-left+1);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值