Leetcode每天五题-03

  1. 搜索旋转排序数组

假设按照升序排序的数组在预先未知的某个点上进行了旋转。( 例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] )。
搜索一个给定的目标值,如果数组中存在这个目标值,则返回它的索引,否则返回-1。你可以假设数组中不存在重复的元素。
你的算法时间复杂度必须是 O(log n) 级别。

示例 1:

输入: nums = [4,5,6,7,0,1,2], target = 0
输出: 4

示例 2:

输入: nums = [4,5,6,7,0,1,2], target = 3
输出: -1

备注

做了好久,感觉代码写的也不是很好。

class Solution {
    public int search(int[] nums, int target) {
        if(nums == null || nums.length == 0)
            return -1;
        int ans = searchCore(nums,0,nums.length -1 ,target);   
        return ans;
    }
    public int searchCore(int[] arr,int low,int high,int target){
        int mid;
        int ans = -1;
        mid = (low + high) >> 1;
        if(low > high){
            return -1;
        }
        if(arr[mid] == target){
            return mid;
        }
        //左半边有序 且target在这个范围之内
        else if(arr[low] < arr[mid] && target < arr[mid] && target >= arr[low]){
            ans =  searchCore(arr,low,mid-1,target);
        }
        //右半边有序 且target在这个范围之内
        else if(arr[mid] < arr[high] && target <= arr[high] && target > arr[mid]){
            ans = searchCore(arr,mid+1,high,target);
        }
        if(ans == -1){
            ans =  searchCore(arr,low,mid-1,target);
        }
        return ans!=-1? ans : searchCore(arr,mid+1,high,target);
    }
}
  1. 在排序数组中查找元素的第一个和最后一个位置

给定一个按照升序排列的整数数组 nums,和一个目标值 target。找出给定目标值在数组中的开始位置和结束位置。

你的算法时间复杂度必须是 O(log n) 级别。如果数组中不存在目标值,返回 [-1, -1]。

示例 1:

输入: nums = [5,7,7,8,8,10], target = 8
输出: [3,4]

示例 2:

输入: nums = [5,7,7,8,8,10], target = 6
输出: [-1,-1]

class Solution {
    public int[] searchRange(int[] nums, int target) {
        
        int[] ans = new int[]{-1,-1}; 
        //讨论区看到的解法,可以不用写两个二分
        int start = binarySearch(nums,target - 0.5);
        int stop = binarySearch(nums,target + 0.5);
        
        if(stop == -1 || nums[stop] != target){
            return ans;
        }
        ans[0] = start + 1;
        ans[1] = stop;
        return ans;
    }
    public int binarySearch(int [] nums ,double k){
        int low = 0;
        int high = nums.length -1;
        
        while(low <= high){ // = 是必须的[5 7 7 8 8 10] t = 8
            int mid = (low + high) >> 1;
            if(nums[mid] < k)
                low = mid + 1;
            else
                high = mid -1;
        }
        return high;
    }
}

  1. 接雨水

给定 n 个非负整数表示每个宽度为1的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。

image

上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水

抄的讨论区的代码,还有另一种思路是找出最高点分别从两边往最高点遍历:如果下一个数比当前数小,说明可以接到水。

示例:

输入: [0,1,0,2,1,0,1,3,2,1,2,1]
输出: 6

class Solution {
    public int trap(int[] height) {
        if(height == null || height.length == 0)
            return 0;
        int n = height.length;
        int left[] = new int[n];
        int right[] = new int[n];
        // left[i]表示i左边的最大值,right[i]表示i右边的最大值
        for(int i = 1;i<n;i++){
            left[i] = Math.max(left[i-1],height[i-1]);
            right[n - i - 1] = Math.max(right[n-i],height[n-i]);
        }
        int ans = 0;
        int level = 0;
        //只要从1..n-2
        for(int i=1;i<n-1;i++){
            level = Math.min(left[i],right[i]);
            ans += level > height[i] ? level - height[i] : 0;
        }
        return ans;
    }
}
  1. 全排列

给定一个没有重复数字的序列,返回其所有可能的全排列。

示例:

输入: [1,2,3]
输出:
[
[1,2,3],
[1,3,2],
[2,1,3],
[2,3,1],
[3,1,2],
[3,2,1]
]

	public List<List<Integer>> permute(int[] nums) {
		if (nums == null || nums.length == 0)
			return Collections.EMPTY_LIST;
		List<List<Integer>> ret = new ArrayList<List<Integer>>();
		List<Integer> ans = new ArrayList<>();
		collect(ret, ans, nums);
		return ret;
	}

	public void collect(List<List<Integer>> ret, List<Integer> ans, int[] nums) {
		if (ans.size() == nums.length) {
			ret.add(new ArrayList<Integer>(ans));
			return;
		}
		for (int i = 0; i < nums.length; i++) {
			// 保证没有重复的元素
			if (ans.contains(Integer.valueOf(nums[i])))
				continue;
			ans.add(nums[i]);
			collect(ret, ans, nums);
			ans.remove(Integer.valueOf(nums[i]));
		}
	}
  1. 旋转图像

给定一个 n × n 的二维矩阵表示一个图像。将图像顺时针旋转 90 度。

说明:

你必须在原地旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要使用另一个矩阵来旋转图像。

示例 :

给定 matrix =
[
[1,2,3],
[4,5,6],
[7,8,9]
],
原地旋转输入矩阵,使其变为:
[
[7,4,1],
[8,5,2],
[9,6,3]
]

备注:

参考CodeInterView,交换的过程有点复杂,不是很清楚

	class Solution {
		public void rotate(int[][] matrix) {
			if (matrix == null || matrix.length == 0 || matrix[0].length == 0) {
				return;
			}
			int tr = 0;
			int tc = 0;
			int dr = matrix.length - 1;
			int dc = matrix[0].length - 1;
			while (tr < dr) {
				rotateCore(matrix, tr++, tc++, dr--, dc--);
			}
		}

		public void rotateCore(int[][] m, int tr, int tc, int dr, int dc) {
			int times = dc - tc;
			int tmp = 0;
			for (int i = 0; i < times; i++) {
				tmp = m[tr][tc + i];
				m[tr][tc + i] = m[dr - i][tc];
				m[dr - i][tc] = m[dr][dc - i];
				m[dr][dc - i] = m[tr + i][dc];
				m[tr + i][dc] = tmp;
			}
		}
	}

讨论区解法:

旋转前:1 2 3 / 4 5 6 / 7 8 9

旋转后:7 4 1 / 8 5 2 / 9 6 3

可以看到旋转后第一行的元素为原来数组从下往上数每行的第一个元素,所以设 i 为行号,j 为列号,n 为行数。 则若将二维数组看成一维数组,则matrix[i][j]转换后里面的元素的下标为 n * (n - j - 1) + i

    public void rotate(int[][] matrix) {
        int n = matrix.length;
        Map<Integer, Integer> map = new HashMap<>();
        //将二维数组中的元素值放入哈希表,key为将二维数组看成一维数组时的数组下标(即0, 1, 2, 3 ...)
        for (int i = 0, k = 0; i < matrix.length; i++){
            for (int j = 0; j < matrix[i].length; j++, k++){
                map.put(k, matrix[i][j]);
            }
        }
        //将二维数组每个元素的值置换为运算后的看作一维数组时的数组下标
        for (int i = 0; i < matrix.length; i++){
            for (int j = 0; j < matrix[i].length; j++){
                matrix[i][j] = n * (n - j - 1) + i;
            }
        }
        //再用置换后的二维数组的元素值作为键,取出哈希表中的值,并将此值放入二维数组
        for (int i = 0, k = 0; i < matrix.length; i++){
            for (int j = 0; j < matrix[i].length; j++, k++){
                matrix[i][j] = map.get(matrix[i][j]);
            }
        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值