0034_Search for a Range

本文介绍了一种在已排序数组中查找目标值起始与终止位置的算法,通过两次二分查找实现,确保了O(log n)的时间复杂度。

Given an array of integers sorted in ascending order, find the starting and ending position of a given target value.

Your algorithm’s runtime complexity must be in the order of O(log n).

If the target is not found in the array, return [-1, -1].

For example,
Given [5, 7, 7, 8, 8, 10] and target value 8,
return [3, 4].

JAVA

方法一

  由于数组有序,因此使用二分查找。首先找到一个target,然后对其左侧循环进行二分查找,但是只保留最后找到的那个,再对其右侧循环进行二分查找,同样只保留最后找到的那一个。时间效率排在4/5左右。

public class Solution {
    public int[] searchRange(int[] nums, int target) {
        int [] result = {-1,-1};
        int mid = -1;
        int left = 0; 
        int right = nums.length - 1;
        boolean findTarget = false;
        while(left <= right){
            mid = (left + right) / 2;
            if(target == nums[mid]){
                result[0] = mid;
                result[1] = mid;
                break;
            }else if(target > nums[mid]){
                left = mid + 1;
            }else{
                right = mid - 1;
            }
        }
        findTarget = true;
        while(findTarget && result[0] != -1){
            left = 0;
            right = result[0] - 1;
            findTarget = false;
            while(left <= right){
                mid = (left + right) / 2;
                if(target == nums[mid]){
                    result[0] = mid;
                    findTarget = true;
                    break;
                }else if(target > nums[mid]){
                    left = mid + 1;
                }else{
                    right = mid - 1;
                }
            }
        }
        findTarget = true;
        while(findTarget && result[1] != -1){
            left = result[1] + 1;
            right = nums.length - 1;
            findTarget = false;
            while(left <= right){
                mid = (left + right) / 2;
                if(target == nums[mid]){
                    result[1] = mid;
                    findTarget = true;
                    break;
                }else if(target > nums[mid]){
                    left = mid + 1;
                }else{
                    right = mid - 1;
                }
            }
        }

        return result;
    }
}

方法二

  由于觉得方法一的效率不应该那么差,毕竟达到了O(log2N),于是重新查看寻找优化的方法。后来发现,由于在循环查找左侧的target时,由于已经找到了一个target在当前查找范围的右侧,而数组是升序的,所以不可能出现找到的数比target大的情况,因此去掉else部分;同理,在循环查找右侧target时,也不会出现小于target的情况,同样去掉else部分。虽然去掉的都是永远不会执行的语句,但是时间快了2ms,效率达到前1/4。
  同样的代码再次执行时,时间比方法一快了1ms,效率达到前2/3。。。可见效率好坏还是要看服务器的。。。

public class Solution {
    public int[] searchRange(int[] nums, int target) {
        int [] result = {-1,-1};
        int mid = -1;
        int left = 0; 
        int right = nums.length - 1;
        boolean findTarget = false;
        while(left <= right){
            mid = (left + right) / 2;
            if(target == nums[mid]){
                result[0] = mid;
                result[1] = mid;
                break;
            }else if(target > nums[mid]){
                left = mid + 1;
            }else{
                right = mid - 1;
            }
        }
        findTarget = true;
        while(findTarget && result[0] != -1){
            left = 0;
            right = result[0] - 1;
            findTarget = false;
            while(left <= right){
                mid = (left + right) / 2;
                if(target == nums[mid]){
                    result[0] = mid;
                    findTarget = true;
                    break;
                }else if(target > nums[mid]){
                    left = mid + 1;
                }
            }
        }
        findTarget = true;
        while(findTarget && result[1] != -1){
            left = result[1] + 1;
            right = nums.length - 1;
            findTarget = false;
            while(left <= right){
                mid = (left + right) / 2;
                if(target == nums[mid]){
                    result[1] = mid;
                    findTarget = true;
                    break;
                }else if(target < nums[mid]){
                    right = mid - 1;
                }
            }
        }

        return result;
    }
}
Sure, here's the previous implementation of BST: ```python class Node: def __init__(self, key): self.left = None self.right = None self.val = key class BST: def __init__(self): self.root = None def insert(self, key): self.root = self._insert(self.root, key) def _insert(self, node, key): if node is None: return Node(key) else: if key < node.val: node.left = self._insert(node.left, key) else: node.right = self._insert(node.right, key) return node def search(self, key): return self._search(self.root, key) def _search(self, node, key): if node is None or node.val == key: return node elif key < node.val: return self._search(node.left, key) else: return self._search(node.right, key) ``` And here's the implementation of `range_search`: ```python def range_search(bst, r): result = [] _range_search(bst.root, r[0], r[1], result) return result def _range_search(node, min_val, max_val, result): if node is None: return if min_val <= node.val <= max_val: _range_search(node.left, min_val, max_val, result) result.append(node.val) _range_search(node.right, min_val, max_val, result) elif node.val < min_val: _range_search(node.right, min_val, max_val, result) else: _range_search(node.left, min_val, max_val, result) ``` The `range_search` function takes a BST and a range `r` as input. It initializes an empty list `result` which will contain the nodes within the range. `_range_search` is a recursive helper function. It takes a node, a minimum value `min_val`, a maximum value `max_val`, and the `result` list as input. If the node is within the range, it recursively calls itself on the left and right subtrees, adds the node's value to the result list, and then recursively calls itself on the left and right subtrees again. If the node's value is less than the minimum value of the range, it only recursively calls itself on the right subtree. If the node's value is greater than the maximum value of the range, it only recursively calls itself on the left subtree. Finally, the `range_search` function calls `_range_search` on the root node of the BST and returns the result list.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值