1. 程式人生 > >未排序陣列中累加和為給定值的系列問題

未排序陣列中累加和為給定值的系列問題

題目一:Zero Sum Subarray

給定一整形陣列,返回序列和為0的子陣列的起始和結束下標。

比如:int[] array={-3,1,2,-3,4};   返回(0,2)和(1,3)。

題解:使用hashmap儲存陣列中從0開始到索引i的子段和,在將值push進map之前,先檢查map中是否已經存在,

若存在則表示找到一組。

注意:map中的鍵值對key表示cursum,而value應表示在index之前的sum為多少。這是為了能成功返回第一組(0,2),

所以事先先將(0,0)的鍵值對put進map中,則當index=2時,才能找到(0,2)這個滿足要求的子陣列!!!

//zero sum subarray
    public void subarraySum(int[] data)
    {
    	HashMap<Integer,Integer> map=new HashMap();
    	map.put(0, 0);//necessary~
    	int cursum=0;
    	for(int i=0;i<data.length;i++)
    	{
    		cursum+=data[i];
    		if(map.containsKey(cursum))
    		{
    			System.out.println("下標:"+map.get(cursum)+"到"+i);
    		}
    			map.put(cursum,i+1);//i+1之前的子段和為cursum;
    	}
    }

      但是該例程若在(0,2)的和為0,且(3,5)的和為零時,那麼(0,5)的和也為0,但是結果沒有給出。

題目二:Subarray Sum Closest

給定一個整型陣列,找到和最接近0的子序列。

返回該子陣列的起始和結束下標。

比如:Given [-3, 1, 1, -3, 5], return [0, 2], [1, 3], [1, 1], [2, 2] or [0, 4].

解析:因要求的子串和不固定,所以不適合再用雜湊表的方法,使用排序可在O(n*logn)內解決。

具體步驟:

1.首先遍歷一遍陣列求的子串和;

2.對子串和排序;

3.逐個比較相鄰兩項差值的絕對值,返回差值絕對值最小的兩項。

這種方法的時間複雜度主要集中在排序上,由於除了記錄子串和之外,還需記錄索引,故引入pair類。最後排序時先按照sum值先排序,再按照索引值排序。

import java.util.*;
public class TestClass {
    public static void main(String args[]) {
	  TestClass test=new TestClass();

			int[] array={-3,1,1,-3,5};
			Result res=test.subarraySumClosest(array);
			System.out.println(""+res.begin+" "+res.end);
    }
//sum subarray closest
    public Result subarraySumClosest(int[] data)
    {
    	if(data == null||data.length <= 1)
    		return new Result(0,0);
    	Pair[] array=new Pair[data.length+1];//array的長度為data.length+1
    	array[0]=new Pair(0,0);//array[0]表示data[0]之前的和,設為0;
    	       //類似連結串列中dummy頭結點的做法,避免了對單個子串和是否為最小情況的單獨考慮;
    	int cursum=0;
    	for(int i=1;i<=data.length;i++)
    	{
    		cursum+=data[i-1];
    		array[i]=new Pair(cursum,i);
    	}
    	//對array按規則排序
    	Arrays.sort(array,new Comparator<Pair>(){
    		public int compare(Pair a,Pair b)//先按sum排序
    		{
    				return a.sum-b.sum;
    		}
    	});
    	int min_subsum=Integer.MAX_VALUE;
    	int closest_p=1;
    	for(int i=1;i<array.length;i++)
    	{
    		if(array[i].sum-array[i-1].sum < min_subsum)
    		{
    			min_subsum=array[i].sum-array[i-1].sum;
    			closest_p=i;
    		}
    	}
    	//排序後大的index可能排在了小的index的前面;
    	int begin=Math.min(array[closest_p].index, array[closest_p-1].index);
    	int end=Math.max(array[closest_p].index, array[closest_p-1].index)-1;// end要減去1;
    	Result result=new Result(begin,end);
    	return result;
    }
       
    class Pair
    {
    	int sum;//sum存放陣列當前下標之前的字首陣列和!!!
    	int index;//index存放陣列下標
    	public Pair(int sum,int index)
    	{
    		this.sum=sum;
    		this.index=index;
    	}
    }
    class Result
    {
    	int begin;
    	int end;
    	public Result(int begin,int end)
    	{
    		this.begin=begin;
    		this.end=end;
    	}
    }
}

題目三:

給定一個無序陣列,其中元素可正,可負,可0,給定一個整數k。求array所有子陣列中累加和為k的最長子陣列長度。

變型題目:

1 。陣列中元素可正,可負,可0,求所有子陣列中正數與負數個數相等的最大子陣列長度

2 。陣列中元素只有1或0,求所有子陣列中1和0個數相等的最長子陣列長度

原問題程式碼如下:仍利用Zero Sum Subarray的方法,map中只記錄一個累加和最早出現的位置。

 public int getMaxLength(int[] array,int k)
   {
	   if(array == null||array.length == 0)
		   return 0;
	   int len=0;
	   int cursum=0;
	   HashMap<Integer,Integer> map=new HashMap();
	   map.put(0,0);//0之前的累加和為0;
	   for(int i=0;i<array.length;i++)
	   {
		  cursum+=array[i];
		 if(map.containsKey(cursum-k))
		 {
			 len=Math.max(len, i-map.get(cursum-k)+1);
		 }
		 if(!map.containsKey(cursum))
		 {
			 map.put(cursum,i+1);//i+1之前的累加和為cursum且cursum第一次出現;
		 }
	   }
	   return len;
 }

第一個補充問題,先把正數全部變為1,負數變為-1,0不變,求累加和為0的最長子陣列長度即可;

第二個補充問題,把0全部變為-1,1不變,求累加和為0的最長子陣列長度即可。

相關推薦

排序陣列累加給定系列問題

題目一:Zero Sum Subarray 給定一整形陣列,返回序列和為0的子陣列的起始和結束下標。 比如:int[] array={-3,1,2,-3,4};   返回(0,2)和(1,3)。 題解:使用hashmap儲存陣列中從0開始到索引i的子段和,在將值push進m

排序陣列累加給定的最長子陣列系列問題

牛客網左程雲第二課第三題,這是一個很重要的演算法原型。 問題:給定一個無序陣列 arr,其中元素可正、可負、可 0,給定一個整數 k。求 arr 所有的子陣列中累加和為 k 的最長子陣列長度。  要求:時間複雜度 O(N) 分析:本題和未排序正數陣列中累加和為給定值的最長子

排序陣列累加給定的最長子陣列

題目給定一個無序陣列arr,其中元素可正,可負,可0,給定一個整數k。求arr所有的子陣列中累加和為k的最長子陣列長度。分析為了解答題目,引入一個概念,s(i)代表子陣列arr[0..i]所有元素的累加和。那麼子陣列arr[j-1, i](0<=j<=i<a

程式設計師面試一百題-10-在排序陣列查詢給定的兩個數字

1-題目 : 輸入一個已經按升序排序過的陣列和一個數字,在陣列中查詢兩個數,使得它們的和正好是輸入的那個數字;要求時間複雜度是O(n);如果有多對數字的和等於輸入的數字,輸出任意一對即可。 2-示例 : 輸入 : 1、2、4、7、11、15和15 輸出 : 4、11 3-思路 :

8.9 不重複列印排序陣列相加給定的所有二元組三元組

【題目】:   給定排序陣列arr和整數k,不重複列印arr中所有相加和為k的不降序二元組   例如:     arr=[-8, -4, -3, 0, 1, 2, 4, 5, 8, 9],k=10,列印結果為:     1,9     2,8   【補充題目】:   給定排序陣列ar

題目三:給定一個數組,可以正、負0,請返回累加給定k的最長子陣列長度。

import java.util.HashMap; /** * * 2、給定一個數組,值可以為正、負和0,請返回累加和為給定值k的最長子陣列長度。 * 咱們可以反推,比如:1- 100,陣列和為1000. * 要求最長和為300的子陣列,我可以反著求第一

《程序員代碼面試指南》第八章 數組矩陣問題 不重復打印排序數組相加給定的所有二元組三元組

esc created ria .com pre edate scrip public int 題目 不重復打印排序數組中相加和為給定值的所有二元組和三元組 java代碼 package com.lizhouwei.chapter8; /** * @Descriptio

Three Sum(找出陣列,所有三個數字的組合,其給定的情況)

import java.util.ArrayList; import java.util.Arrays; import java.util.List; /** * Three Sum * * Given an array S of n integ

給定陣列找出兩個元素給定的所有元素對

Design an algorithm to find all pairs of integers within an array which sum to a specified value.  使用hash map: 1假設V為給定的值,A為給定的陣列。 2建立has

給定陣列選取任意個數(可重複),使其給定

回溯法練習:從給定有序陣列中選取任意個數(可重複),使其和為給定值(leetcode39):Example 1:Input: candidates = [2,3,6,7], target = 7A solution set is: [ [7], [2,2,3] ]思路

3.6 在二叉樹找到累加指定的最長路徑長度

【題目】:   給定一棵二叉樹的頭節點head和一個32位整數sum,二叉樹節點值型別為整型,求累加和為sum的最長路徑長度。路徑是指從某個節點往下,每次最多選擇一個孩子節點或者不選所形成的的節點鏈   例如, 二叉樹如圖所示               -3           3   &

指定整數陣列輸出一整數的所有組合

題目:編寫一個函式,在陣列a[10] = {1,3,5,7,9,11,13,15,17}中輸出和為25的所有整數組合 思想:遞迴,探底一種情況後返回前一種狀態。 程式碼: #include <stdio.h> #include <string.h>

852. Peak Index in a Mountain Array(python+cp)(以及尋找排序陣列絕對值最小的

題目: Let’s call an array Aa mountain if the following properties hold: A.length >= 3 There exists

每天一道LeetCode-----找到二叉樹所有給定的路徑

Path Sum 判斷二叉樹中有沒有一條從根節點到葉子節點的路徑元素和為給定值 只需要遍歷所有路徑即可,需要注意的是對葉子節點的判斷,需要滿足左右兩個節點都是空的條件時才為葉子節點 程式碼如下 /** * Definition for a

陣列兩個數指定陣列下標

散列表方式: public void findBathIndex(int[] arr,int k){ if(arr==null){ return;

給定一整數在有序的整數陣列找出與給定最接近的k個整數

思路:首先找出給定值在給定陣列中的插入位置(不是真的將給定值插入給定陣列),然後以此位置為基準,向左或向右依次找出最接近的k個整數。 難點:個人在處理過程中的難點在於向左或向右移動過程中的確切位置的確

Two Sum 從陣列找到兩個位置的相加給定目標的

Example Given nums = [2, 7, 11, 15], target = 9, Because nums[0] + nums[1] = 2 + 7 = 9, return [0, 1]. public int[] twoSum(int[

[Swift]LeetCode34. 在排序陣列查詢元素的第一個最後一個位置 | Find First and Last Position of Element in Sorted Array

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

leetcode題庫——在排序陣列查詢元素的第一個最後一個位置

題目描述: 給定一個按照升序排列的整數陣列 nums,和一個目標值 target。找出給定目標值在陣列中的開始位置和結束位置。 你的演算法時間複雜度必須是 O(log n) 級別。 如果陣列中不存在目標值,返回 [-1, -1]。 示例 1: 輸入: nu

leetcode 34在排序陣列查詢元素的第一個最後一個位置 python

給定一個按照升序排列的整數陣列 nums,和一個目標值 target。找出給定目標值在陣列中的開始位置和結束位置。 你的演算法時間複雜度必須是 O(log n) 級別。 如果陣列中不存在目標值,返回 [-1, -1]。 示例 1: 輸入: nums = [5,7,7,8,8,