赞
踩
1. 用T函数表示法计算时间复杂度
例如二分法 T(n) = T(n/2) + O(1),将规模为n的问题降低为规模为n/2的问题
1)首先 T 代表的是 Time Complexity,n 代表的是问题规模(二分法里就是数组的大小)。
那么 T(n) 代表的就是:求处理问题规模为n的数据的时间复杂度是多少。
2)然后 O 代表的是时间复杂度。O(1) 就意味着,你大概用一个 if 语句,或者简单的加加减减,就可以完成。O 在这里的意思是数量级约等于。在 O 的世界里,我们只考虑最高项是什么,不考虑系数和常数项。
2. 递归 (从后往前推导,降低所给问题的规模)
1)递归的三要素
2)Stack Overflow
摘要:我们通常所说的内存空间,包含了两个部分:栈空间 (stack space) 和 堆空间 (heap space)
栈空间 (Stack space):当一个程序在执行的时候,操作系统为了让进程可以使用一些固定的、不被其他进程侵占的空间用于函数调用、递归等操作,会开辟一个固定大小的空间 (比如8M) 给进程使用。这个空间通常不会太大,否则内存的利用率会很低,这个空间就是我们所说的 Stack space。
栈空间里存储的内容,会在函数执行结束的时候被销毁。
栈空间主要包含:
堆空间 (Heap space):通常对象、new出来的东西都会存放在堆空间中。堆空间里存放的内容在函数执行结束后不会被销毁。
stack overflow: 我们通常所说的栈溢出,是指在函数调用或递归调用时,开辟了过多的内存,超出了操作系统分配的那个很小的固定空间导致的。
3)递归深度
定义:递归深度就是递归函数在内存中,同时存在的最大次数。
函数的调用,会在内存的栈空间中开辟新空间,用来存放子函数。递归函数会不断占用栈空间,因而太深的递归会导致栈空间溢出。
3. 二分法
1)基本原理:
每次取数组当前区间的中点,并与目标值target比较,根据比较结果缩减一半搜索范围,时间复杂度为O(logn)
2)基本条件:有序数组
3)递归实现:
- class Solution {
- public int search(int[] nums, int target) {
- return binarySearch(nums,0,nums.length-1,target);
- }
-
- // 通过缩减区间,来达到降低问题规模的目的
- private int binarySearch(int[] nums, int start, int end, int target){
- // 递归出口
- if(start > end){
- return -1;
- }
-
- int mid = start + (end - start)/2;
- if(nums[mid] == target){
- return mid;
- }
- if(nums[mid] < target){
- return binarySearch(nums,mid+1,end,target);
- }
- return binarySearch(nums,start,mid-1,target);
- }
- }
4)非递归-无死循环实现:
- public class Solution {
- /**
- * @param A an integer array sorted in ascending order
- * @param target an integer
- * @return an integer
- */
- public int findPosition(int[] nums, int target) {
- if (nums == null || nums.length == 0) {
- return -1;
- }
-
- int start = 0, end = nums.length - 1;
- // 要点1: start + 1 < end
- while (start + 1 < end) {
- // 要点2:start + (end - start) / 2
- int mid = start + (end - start) / 2;
- // 要点3:=, <, > 分开讨论,mid 不+1也不-1
- if (nums[mid] == target) {
- return mid;
- } else if (nums[mid] < target) {
- start = mid;
- } else {
- end = mid;
- }
- }
-
- // 要点4: 循环结束后,单独处理start和end
- if (nums[start] == target) {
- return start;
- }
- if (nums[end] == target) {
- return end;
- }
- return -1;
- }
- }
注: 为什么while条件要写成start + 1 < end ?
意味着当数组区间中剩余2个数时,退出循环。因为在某些情况下 --- 寻找最右数,会陷入死循环
例如[1,1] target = 1,取中点并与target比较后,区间范围依然是[1,1],没有缩小,导致代码超时。
4. 相关例题
leetcode: 509. 斐波那契数,704. 二分查找,34. 在排序数组中查找元素的第一个和最后一个位置,剑指 Offer II 069. 山峰数组的顶部
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。