(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;}
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的所有子数组。
- (2/500)打印出和为0的所有子数组
- 给出一个数组,打印出这个数组的所有的子数组
- 打印出数组的所有子集
- 使用递归打印出计算机某个文件夹下的所有文件夹和子文件
- 打印出二叉树中结点值的和为输入整数的所有路径
- 输入一个正数s,打印出所有和为s的连续正数序列
- 给一个正整数sum,打印出所有和为sum的连续正整数序列之和。
- 打印出大小为n的数组(可能有重复元素)里所有可能的组合
- 输入一个整数和一棵二元树,打印出所有和为该整数的二元树中的路径
- 输入一个正整数数组,输入一个正整数数组,把数,打印能拼接出的所有数字中最小的一个。例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为321323。
- 《剑指Offer》面试题:打印出二叉树中结点值的和为输入整数的所有路径
- 【算法-java】打印出二叉树中结点值的和为输入整数的所有路径
- 打印出所有该目录下的文件和文件夹
- 打印出所有该目录下的文件和文件夹
- 【31】给定一个二叉树打印出所有从根结点到叶子结点路径和为 k 的路径
- 输入一个正数s,打印出所有和为s的连续正数序列(至少包含两个数)
- 在二叉树中打印出从某个节点(r)开始和为定值(sum)的所有路径
- 【31】给定一个二叉树打印出所有从根结点到叶子结点路径和为 k 的路径
- spring-JDBCTemplate配置
- ReentrantLock实现原理深入探究
- Java中Array.sort()的几种用法
- 不忘初心,方得始终
- 寄存器
- (2/500)打印出和为0的所有子数组
- C++上机实验五——项目一 数组分离
- Java内存模型(JMM) 概述
- pom文件
- CSDN 我来了 坚持一个月两篇
- Linux常用命令学习(二)
- 二叉树遍历算法的应用(java版)
- python web下的服务器结构——WSGI容器、Nginx、Flask之间的关系
- CH37X 常见问题梳理与解决流程