GitXplorerGitXplorer
j

data_structures_and_algorithm_analysis_in_java

public
0 stars
0 forks
0 issues

Commits

List of commits on branch master.
Unverified
3216ead192cc4a92f28dd5708765ec008e4e6e4a

Update README.md

jjialechan committed 8 years ago
Unverified
169d532c1bc37697dc699171e10efa438232141a

Update README.md

jjialechan committed 8 years ago
Unverified
74e88343bd381c84ad6ef2ea6e2ee3c71060c293

Update README.md

jjialechan committed 8 years ago
Unverified
bb3e1ff42df12784ee080d91ea2f06f29961fd22

Update README.md

jjialechan committed 8 years ago
Unverified
5265d45658ca136d63981dce2b246a3c31e083e5

Update README.md

jjialechan committed 8 years ago
Unverified
e5d849d1f23e9f3e958af6fdee0ff9e0f6e0dff7

Delete 最大子序列和问题.md

jjialechan committed 8 years ago

README

The README file for this repository.

数据结构与算法分析知识整理

最大子序列和问题

给定(可能有负数)整数序列A1, A2, A3..., An求这个序列中子序列和的最大值。   
(为方便起见,如果所有整数均为负数,则最大子序列和为0)。   
例如:输入整数序列: -2, 11, 8, -4, -1, 16, 5, 0,则输出答案为35,即从A2~A6。

算法一:穷举法

public static int maxSub(int[] a) {
    int maxSum = 0;
    for (int i = 0; i < a.length; i++) {        //i为子序列的左边界
        for (int j = i; j < a.length; j++) {    //j为子序列的右边界
            int thisSum = 0;
            for (int k = 0; k <= j; k++)        //迭代子序列中的每一个元素,求和
                thisSum += a[k];
            if (thisSum > maxSum)
                maxSum = thisSum;
        }
    }
    return maxSum;
}

时间复杂度为O(N^3)

算法二:改进穷举法

/** 
 * 对前面计算的结果加以利用 
 * 减去一层循环 
 */  
public static int maxSub(int a[]) {  
    int maxSum = 0;  
    for (int i = 0; i < a.length; i++) {  
        int sum = 0;  
        for (int j = i; j < a.length; j++) {  
            sum += a[j];  
            if (maxSum < sum)  
                maxSum = sum;  
        }  
    }  
    return maxSum;  
}  

时间复杂度为O(N^2)

算法三:分治

最大子序列的和只可能出现在3个地方:

  1. 出现在输入数据的左半部分
  2. 出现在输入数据的右半部分
  3. 跨越输入数据的中部而位于左右两个部分

前两种情况可以递归求解,第三种情况的最大和可以通过求出前半部分(包含前半部分的最后一个元素)的最大和以及后半部分(包括后半部分的第一个元素)的最大和,再将二者相加得到。

public int maxSub(int[] a, int left, int right) {
    if (left == right)
        if (a[left] > 0)
            return a[left];
        else
            return 0;
    int center = (left + right) / 2;//分解  
    int maxLeftSum = maxSub(a, left, center);//左边递归  
    int maxRightSum = maxSub(a, center + 1, right);//右边递归  
    //处理中间包含center左右边界的最大和情况  
    int maxLeftBorderSum = 0, leftBoderSum = 0;
    for (int i = center; i >= left; i--) {
        leftBoderSum += a[i];
        if (maxLeftBorderSum < leftBoderSum)
            maxLeftBorderSum = leftBoderSum;
    }
    int maxRightBorderSum = 0, rightBorderSum = 0;
    for (int i = center + 1; i <= right; i++) {
        rightBorderSum += a[i];
        if (maxRightBorderSum > rightBorderSum)
            maxRightBorderSum = rightBorderSum;
    }
    //问题合并(治)  
    return max(maxLeftSum, maxLeftBorderSum + maxRightBorderSum, maxRightSum);
}

//可变参数的使用,jdk1.5及以上  
public int max(int... args) {
    int max = args[0];
    for (int i = 1; i < args.length; i++)
        if (max < args[i])
            max = args[i];
    return max;
}

时间复杂度为O(NlogN)

算法四:

public int maxSub(int[] a) {
    int sum = 0, maxSum = 0;
    for (int i = 0; i < a.length; i++) {
        sum += a[i];
        if (sum > maxSum)
            maxSum = sum;
        else if (sum < 0)
            sum = 0; //如果sum<0,就没有必要将前面的序列继续代入了,将sum=0  
    }
    return 0;
}

时间复杂度为O(N)

表、栈和队列

表(List)

  • ArrayList查找时间为O(1),添加/删除最差时间为O(N)
  • LinkedList查找为O(N),添加/删除最差时间为O(1)

栈(Stack)

  • 用表实现
  • 后进先出

队列(Queue)

  • 用表实现
  • 先进先出