find largest sub array

最大子数组求和算法
本文介绍了两种解决最大子数组求和问题的方法:分治法和线性搜索法。分治法通过递归将问题分解为子问题并考虑中间子数组,复杂度为O(n log n)。线性搜索法则通过一次遍历实现,复杂度为O(n)。

There are two ways to solve the problem of largest sub array:

1: divide-and-conquer method

2: linear search method

Now let me introduce them one by one.

1: divide-and-conquer method

The core idea of it is to divide the array to two sub arrays, you need to find out the largest sub array from the above two sub arrays, and the most important thing is you can not ignore the middle sub array cross the middle node. So at each level, you can find out 3 sub largest sub arrays, the left one, the right one and the middle one cross the middle node, and then choose the max one as the largest sub array of the above level. Recursively divide the sub array of each level until each sub array only has one node that is the leaf node.

The detail steps of this algorithm are as follow:

1).find out the middle element's position named m.

2).divide the array to tow sub arrays, the left one is from 0 until m, the right one is from m+1 until the end of the array.

3).make each sub array as the parameter and call the method itself recursively.

4).find out the middle largest sub array crosses the middle node which position is m.

5).compare the three sub array, find out the largest one

The recursion is such that:

    T(n) =  O(1)for n = 1

T(n) = 2(T(n/2))+O(n) for all n > 1

So the complexity of T(n) is O(nlgn).

The following is the implement of divide-and conquer method by java.

private int[] findLargestSubArray1 (int[] array, int l, int r){
    if(l >= r){
        return array;
    }else{
        int m = (l+r)/2;
        int[] l_result =findLargestSubArray1(array,l, m);
        int[] r_result = findLargestSubArray1(array,m+1,r);
        int[] m_result =middleLargetSubArray(array,l,r,m);
        if(l_result[2] > r_result[2]&& l_result[2] > m_result[2]){
            return l_result;
        }else if(r_result[2] >l_result[2] && r_result[2] > m_result[2]){
            return r_result;
        }else{
            return m_result;
        }
    }
}

private int[] middleLargetSubArray(int[] array, int l, int r,int m){
    int l_max = 0;
    int r_max = 0;
    int sum = 0;
    int l_el = 0;
    int r_el = 0;
    for(int i = m;i >= 0;i--){
        sum = sum + array[i];
        if(sum > l_max){
            l_max = sum;
            l_el = i;
        }
    }
    sum = 0;
    for(int i = m+1;i < r;i++){
        sum = sum + array[i];
        if(sum > r_max){
            r_max = sum;
            r_el = i;
        }
    }
    return new int[] {l_el,r_el,l_max+r_max};
}

2: linear search method

The core idea is iterate the array from left to right and sum them, and cache the max sum value and the current subarray after each calculation. If the result is larger than the cached max sum value then replace max sum value with the result. If the result is less than 0,then abandon the cached sub array, make next element as the first element of the new sub array and start the new calculation.

1).iterate the array from left to right.

2).sum the elements that has been iterated.

3).compare the result with the max sum value had been cached, and then to choose the larger one to replace the max sum value.

4).if you find the result has less than 0,you need to abandon the sub array you cache now. from the next element, to findthe new sum array.

The complexity is O(n).

The following is the implement of the linear search by java.

private int[] findLargestSubArray2 (int[] array){
    int new_l_el = 0;
    int l_el = 0;
    int r_el = 0;
    int sum = 0;
    int maxSum = 0;
    for(int i = 0; i < array.length;i++){
        sum = sum + array[i];
        if(sum > maxSum){
            maxSum = sum;
            l_el = new_l_el;
            r_el = i;
        }else if(sum <= 0){
            sum = 0;
            new_l_el = i+1;
        }
    }
    return new int[] {l_el,r_el,maxSum};
}

import os import tqdm import time import numpy as np import numba as nb import networkx as nx import json from pathlib import Path # import igraph as ig SCENE_IDS = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 20, 21, 22, 23, 24, 25, 26 ] @nb.njit(nogil=True, cache=True) def EuclideanDistance3(point_a: np.array, point_b: np.array) -> float: """ Euclidean distance of two given point (3D) """ # return float(np.linalg.norm((point_a - point_b), ord=2)) return float(np.sqrt(np.sum(np.square(np.subtract(point_a, point_b))))) @nb.njit(nogil=True, cache=True) def EuclideanDistance1(point_a: np.array, point_b: np.array) -> float: """ Euclidean distance of two given point (1D) """ return float(np.sqrt(np.square(float(point_a - point_b)))) def Distance(edge, termial, token_dict): point_a = np.array(token_dict[edge]) point_b = np.array(token_dict[termial]) distance = EuclideanDistance3(point_a, point_b) return float(distance) class ShortestPathSensor: def __init__(self, nav_graph_path, token_dict_path, load_scenes=SCENE_IDS) -> None: self.nav_graph_path = nav_graph_path self.token_dict_path = token_dict_path self.load_scenes = load_scenes # build # self.graphs, self.token_dicts = self._BuildNXGraphs(scene_ids=load_scenes) # load only self.graphs, self.token_dicts = self._LoadNXGraphs(scene_ids=load_scenes) def _LoadOriFiles(self, scene_idx): file_name_graph = Path(args.ori_nav_graph_path) / &#39;nav_graph_dict_{}.json&#39;.format(scene_idx) file_name_dict = Path(args.ori_token_dict_path) / &#39;TokenDict_{}.json&#39;.format(scene_idx) with open(file_name_graph, &#39;r&#39;, encoding=&#39;utf-8&#39;) as file: content_graph = json.load(file) with open(file_name_dict, &#39;r&#39;, encoding=&#39;utf-8&#39;) as file: content_dict = json.load(file) return content_graph, content_dict def _BuildNXGraphs(self, scene_ids=SCENE_IDS): graphs = {} token_dicts = {} for scene_id in scene_ids: print("BuildNXGraphs of Scene {}".format(scene_id)) graph_dict, token_dict = self._LoadOriFiles(int(scene_id)) G = nx.Graph() nodes = list(graph_dict.keys()) G.add_nodes_from(nodes) edges = [] weights_dict = {} pbar = tqdm.tqdm(total=len(nodes)) for start_node in nodes: pbar.update() for end_node in graph_dict[start_node]: weight = Distance(start_node, end_node, token_dict) weights_dict[str(&#39;{}_{}&#39;.format(start_node, end_node))] = weight edges.append( (start_node, end_node, weight) ) pbar.close() G.add_weighted_edges_from(edges) largest = max(nx.connected_components(G), key=len) largest_connected_subgraph = G.subgraph(largest) nodes = list(largest_connected_subgraph.nodes()) token_dict_sub = {} for node in nodes: token_dict_sub.update({ node: token_dict[node] }) token_dicts.update({ int(scene_id): token_dict_sub }) if not os.path.exists(str(Path(args.token_dict_path))): os.makedirs(str(Path(args.token_dict_path)), exist_ok=True) with open(str(Path(args.token_dict_path) / &#39;TokenDict_{}.json&#39;.format(scene_id)), &#39;w&#39;, encoding=&#39;utf-8&#39;) as dump_f: json.dump(token_dict_sub, dump_f) new_G = ig.Graph() new_G.add_vertices(len(nodes)) new_G.vs["name"] = nodes edges = [] weights = [] pbar = tqdm.tqdm(total=len(nodes)) for start_node in nodes: pbar.update() start_vs = new_G.vs.find(name=start_node) try: for end_node in graph_dict[start_node]: end_vs = new_G.vs.find(name=end_node) edges.append([start_vs, end_vs]) weight = weights_dict[str(&#39;{}_{}&#39;.format(start_node, end_node))] weights.append(weight) except Exception as e: pass pbar.close() new_G.add_edges(edges) new_G.es["weight"] = weights if not os.path.exists(str(Path(args.nav_graph_path))): os.makedirs(str(Path(args.nav_graph_path)), exist_ok=True) new_G.write_pickle(str(Path(args.nav_graph_path) / &#39;nav_graph_dict_{}.pkl&#39;.format(scene_id))) graphs[int(scene_id)] = new_G return graphs, token_dicts def _LoadNXGraphs(self, scene_ids=SCENE_IDS): graphs = {} token_dicts = {} for scene_id in scene_ids: print( "{}\tLoadNXGraphs of Scene {}".format( str(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())), scene_id ) ) G = ig.Graph.Read_Pickle(str(Path(self.nav_graph_path) / &#39;nav_graph_dict_{}.pkl&#39;.format(scene_id))) graphs[int(scene_id)] = G file_name_dict = Path(self.token_dict_path) / &#39;TokenDict_{}.json&#39;.format(scene_id) with open(file_name_dict, &#39;r&#39;, encoding=&#39;utf-8&#39;) as file: token_dict = json.load(file) token_dicts[int(scene_id)] = token_dict return graphs, token_dicts def get_shortest_paths(self, source: str, target: str, scene_id: int): assert scene_id in self.load_scenes, &#39;wrong scene_id of get_shortest_paths&#39; graph = self.graphs[int(scene_id)] try: source_vs = graph.vs.find(name=str(source)) target_vs = graph.vs.find(name=str(target)) except Exception as e: print(&#39;wrong token of get_shortest_paths: {}&#39;.format(e)) raise Exception(e) shortest_paths = graph.get_shortest_paths( source_vs, to=target_vs, weights=graph.es["weight"], output="vpath", ) if shortest_paths is None or len(shortest_paths) <= 0: print(&#39;get_shortest_paths error, could not found path&#39;) return [] return shortest_paths[0] def get_vs_token(self, vs_index, scene_id: int): assert scene_id in self.load_scenes, &#39;wrong scene_id of get_vs_token&#39; try: graph = self.graphs[int(scene_id)] vs_token = str(graph.vs[vs_index][&#39;name&#39;]) except Exception as e: print(&#39;wrong vs_token of get_vs_token: {}&#39;.format(e)) raise Exception(e) return vs_token 详细解释一下
最新发布
08-26
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值