(2/500)打印出和为0的所有子数组

来源:互联网 发布:苹果app行动监管软件 编辑:程序博客网 时间:2024/05/20 07:38

给定一个整型数组,请打印出元素和为0的所有子数组。
例如,
输入:

{ 4, 2, -3, -1, 0, 4 }
输出:
Sub-arrays with 0 sum are
{ -3, -1, 0, 4 }
{ 0 }

输入:
{ 3, 4, -7, 3, 1, 3, 1, -4, -2, -2 }
输出:
Sub-arrays with 0 sum are
{ 3, 4, -7 }
{ 4, -7, 3 }
{ -7, 3, 1, 3 }
{ 3, 1, -4 }
{ 3, 1, 3, 1, -4, -2, -2 }
{ 3, 4, -7, 3, 1, 3, 1, -4, -2, -2 }

 

1. 傻瓜式方法

傻瓜式方法的想法很简单,遍历数组的所有子数组,并计算它们的和。如果子数组的和等于0,那么就打印它。它的时间复杂度是 O(n3),因为一共有 n(n+1)/2(注:原文n2不对)个子数组,花费的时间是O(n2),然后还要花费 O(n)的时间求元素的和。当然,如果在找子数组的同时计算元素的和,那么这种方法可以优化成O(n2)时间。

C++语言实现:

#include <iostream>#include <unordered_map>using namespace std; // Function to print all sub-arrays with 0 sum present// in the given arrayvoid printallSubarrays(int arr[], int n){    // consider all sub-arrays starting from i    for (int i = 0; i < n; i++)    {        int sum = 0;         // consider all sub-arrays ending at j        for (int j = i; j < n; j++)        {            // sum of elements so far            sum += arr[j];             // if sum is seen before, we have found a sub-array            // with 0 sum            if (sum == 0)                cout << "Subarray [" << i << ".." << j << "]\n";        }    }} // main functionint main(){    int arr[] = { 3, 4, -7, 3, 1, 3, 1, -4, -2, -2 };    int n = sizeof(arr)/sizeof(arr[0]);     printallSubarrays(arr, n);     return 0;}

Java语言实现:

class PrintallSubarrays{    // Function to print all sub-arrays with 0 sum present    // in the given array    public static void printallSubarrays(int arr[])    {        // n is length of the array        int n = arr.length;         // consider all sub-arrays starting from i        for (int i = 0; i < n; i++)        {            int sum = 0;             // consider all sub-arrays ending at j            for (int j = i; j < n; j++)            {                // sum of elements so far                sum += arr[j];                 // if sum is seen before, we have found a sub-array with 0 sum                if (sum == 0)                    System.out.println("Subarray [" + i + ".." + j + "]");            }        }    }     // main function    public static void main (String[] args)    {        int arr[] = { 3, 4, -7, 3, 1, 3, 1, -4, -2, -2 };        printallSubarrays(arr);    }}

输出:
Subarray [0..2]
Subarray [0..9]
Subarray [1..3]
Subarray [2..5]
Subarray [3..9]
Subarray [5..7]

 

2. 使用map打印子数组

我们可以使用map打印所有和为0的子数组,子数组信息存放在另外的数组中并作为map的value。开始,我们创建一个空map存放所有和等于给定值的子数组的的结束下标。其中,key是和,value就是之前提到的另外一个数组,此数组中存放的就是和等于key的所有子数组的结束下标。我们遍历给定数组,在遍历过程中维护目前所遍历过的元素的和。如果元素的和在之前见过,那就意味着至少存在一个子数组和为0,子数组的结束下标就是当前遍历的下标,这样我们就能打印出所有的子数组。

C++语言实现:

#include <iostream>#include <unordered_map>using namespace std; // Function to print all sub-arrays with 0 sum present// in the given arrayvoid printallSubarrays(int arr[], int n){    // create an empty multi-map to store ending index of all    // sub-arrays having same sum    unordered_multimap<int, int> map;     // insert (0, -1) pair into the map to handle the case when    // sub-array with 0 sum starts from index 0    map.insert(pair<int, int>(0, -1));     int sum = 0;     // traverse the given array    for (int i = 0; i < n; i++)    {        // sum of elements so far        sum += arr[i];         // if sum is seen before, there exists at-least one        // sub-array with 0 sum        if (map.find(sum) != map.end())        {            auto it = map.find(sum);             // find all sub-arrays with same sum            while (it != map.end() && it->first == sum)            {                cout << "Subarray [" << (it->second + 1) << ".." << i << "]\n";                it++;            }        }         // insert (sum so far, current index) pair into multi-map        map.insert(pair<int, int>(sum, i));    }} // main functionint main(){    int arr[] = { 3, 4, -7, 3, 1, 3, 1, -4, -2, -2 };    int n = sizeof(arr)/sizeof(arr[0]);    printallSubarrays(arr, n);    return 0;}

Java语言实现:

import java.util.HashMap;import java.util.Map;import java.util.ArrayList; class PrintallSubarrays{    // Utility function to insert <key, value> into the Multimap    private static void insert(Map<Integer, ArrayList> hashMap,                                Integer key, Integer value)    {        // if key is already present        if (hashMap.containsKey(key))        {            hashMap.get(key).add(value);        }else        // key is seen for the first time        {            ArrayList<Integer> list = new ArrayList<Integer>();            list.add(value);            hashMap.put(key, list);        }    }     // Function to print all sub-arrays with 0 sum present    // in the given array    public static void printallSubarrays(int arr[])    {        // n is length of the array        int n = arr.length;         // create an empty Multi-map to store ending index of all        // sub-arrays having same sum        Map<Integer, ArrayList> hashMap = new                                    HashMap<Integer, ArrayList>();         // insert (0, -1) pair into the map to handle the case when        // sub-array with 0 sum starts from index 0        insert(hashMap, 0, -1);         int sum = 0;         // traverse the given array        for (int i = 0; i < n; i++)        {            // sum of elements so far            sum += arr[i];             // if sum is seen before, there exists at-least one            // sub-array with 0 sum            if (hashMap.containsKey(sum))            {                ArrayList<Integer> list = hashMap.get(sum);                 // find all sub-arrays with same sum                for (Integer value: list) {                    System.out.println("Subarray [" + (value + 1) + ".." +  i + "]");                }            }             // insert (sum so far, current index) pair into the Multi-map            insert(hashMap, sum, i);        }    }     // main function    public static void main (String[] args)    {        int A[] = { 3, 4, -7, 3, 1, 3, 1, -4, -2, -2 };        printallSubarrays(A);    }}

输出:
Subarray [0..2]
Subarray [1..3]
Subarray [2..5]
Subarray [5..7]
Subarray [3..9]
Subarray [0..9]

这样,只需遍历一次数组就能求出所有的子数组。

 

练习: 打印出和为非0的所有子数组。

0 0
原创粉丝点击