sequence;
63 |
64 | element_var element;
65 | seq_var element_sum = 0;
66 |
67 | for (int seq_index = 0; seq_index < seq_size; seq_index++) {
68 | std::cin >> element;
69 | element_sum += element;
70 | sequence.push_back(element);
71 | }
72 |
73 | // If the sum of the elements is 0, then we have a list of all 0s. For an
74 | // array with size N, and all values=0, the max amount of splits is N-1.
75 | if (element_sum == 0) {
76 | std::cout << (seq_size - 1) << std::endl;
77 | continue;
78 | }
79 |
80 | // If the sum of the elements is NOT even then we cannot split the sequence
81 | // into two partitions of equal sums. So we can stop here, print out 0 and
82 | // move on to the next test case.
83 | if (element_sum % 2 != 0) {
84 | std::cout << 0 << std::endl;
85 | continue;
86 | }
87 |
88 | std::cout <<
89 | countSplits(sequence.begin(), sequence.end(), element_sum / 2) << std::endl;
90 | }
91 |
92 | return 0;
93 | }
94 |
--------------------------------------------------------------------------------
/Guide/Dynamic Programming/README.md:
--------------------------------------------------------------------------------
1 | # Dynamic Programming Guide
2 |
3 | ## Overview
4 | Dynamic Programming - An algorithm that:
5 |
6 | * Solves a problem by breaking it into smaller subproblems that can then be used to find the answer to the original problem.
7 |
8 | * Gets rid of recursion by using [memoization](http://stackoverflow.com/questions/1988804/what-is-memoization-and-how-can-i-use-it-in-python).
9 |
10 | ## Additional Resources
11 |
12 | The links bellow are resources that can help you more fully understand
13 | dynamic programming.
14 |
15 | [wikipedia dynamic programming](https://en.wikipedia.org/wiki/Dynamic_programming)
16 |
17 | [topcoder dynamic programming](https://www.topcoder.com/community/data-science/data-science-tutorials/dynamic-programming-from-novice-to-advanced/)
--------------------------------------------------------------------------------
/Guide/GraphTheory/JackGoesToRapture/README.md:
--------------------------------------------------------------------------------
1 | # Jack goes to Rapture
2 |
3 | ## Problem
4 | This problem comes from [HackerRank](https://www.hackerrank.com/challenges/jack-goes-to-rapture).
5 | Category: Graph Theory
6 | Difficulty: Medium
7 |
8 | ### Overview
9 | Essentially the problem is giving the following challenge,
10 |
11 | 1. Assume you are given a list of edges for vertices from 1...n.
12 | 2. Find the weight of the path starting at 1 and ending at n such that the
13 | cost of going from 1 to n is minimized. If no such path exists print "NO
14 | PATH EXISTS".
15 | 3. The cost of a path is the maximum weight (cost) of any edge in that path.
16 | 4. No two edges have the same cost and no cost is negative.
17 |
18 | ## Algorithm
19 | ### Overview
20 | The data structure best suited to this problem is Union-Find (UF). UF is
21 | a data structure that efficiently merges groupings of objects together
22 | and checks to see if two objects share the same group. In this case each
23 | integer represents a vertex. It has the following operations,
24 | - find(int i): returns the ID of the group that 'i' is in.
25 | - count(): returns the number of groupings
26 | - connected(int a, int b): returns true if 'a' and 'b' are in the same group.
27 | - union(int a, int b): merges the groups of 'a' and 'b'.
28 |
29 | NOTE: I used the implementation of UF from a [Princeton course](http://algs4.cs.princeton.edu/15uf/UF.java.html).
30 |
31 | Using UF we can union the edges with the smallest weight until we get a
32 | path from 1 to n. By using UF in this way, we minimize the cost of getting
33 | from 1 to n.
34 |
35 | Assumption: We don't care if we get extra edges in our set of minimal cost
36 | edges because fair cost is the max edge cost among all edges. By going from
37 | smallest cost to largest, if we reach the destination we can assume that
38 | all previously used edges have a lower cost.
39 |
40 | ### Pseudo Code
41 | 1. Read in values 3 at a time, creating edges and adding them to a list.
42 | 2. Sort all edges in ascending order by weight (cost).
43 | 3. Iterate through the list of edges, calling union on each pair of vertices
44 | until vertices 1 and n are connected, or until reaching the end of the list.
45 | 4. If there is a path from 1 to n, print the max edge value from that
46 | path. Else, print "NO PATH EXISTS".
47 |
48 | ### Analysis
49 | The best sorting algorithms under average conditions achieve a time
50 | complexity of _O(m*log(m))_. Where m is the number of edges.
51 | Union-Find has a time complexity of _O(log(m))_.
52 | We apply Union-Find a maximum of m times during our loop through the list
53 | of edges.
54 | So the resulting time complexity of this solution is _O(m*log(m))_.
55 |
56 | The longest running test case was #15 at 2.3s. This solution gets a full
57 | score of 80 on HackerRank.
58 |
59 | ## Conclusion
60 | This is a fun problem because it both tests your knowledge of graph theory
61 | and your knowledge of different data structures. Although it can be fun to
62 | try, as far as we know there is no _O(m)_ or _O(log(m))_ solution to this
63 | problem. Other interesting challenges to consider are as follows.
64 | - Does the solution change if edges can have the same weight? If so, how?
65 | - How would you solve this problem if there were so many edges that you
66 | could not fit them all on the same machine?
67 |
--------------------------------------------------------------------------------
/Guide/GraphTheory/JackGoesToRapture/solution.java:
--------------------------------------------------------------------------------
1 | import java.io.*;
2 | import java.util.*;
3 | import java.text.*;
4 | import java.math.*;
5 | import java.util.regex.*;
6 |
7 | public class Solution {
8 |
9 | // This implementation of UnionFind http://algs4.cs.princeton.edu/15uf/UF.java.html
10 | public static class UF {
11 |
12 | private int[] parent; // parent[i] = parent of i
13 | private byte[] rank; // rank[i] = rank of subtree rooted at i (never more than 31)
14 | private int count; // number of components
15 |
16 | /**
17 | * Initializes an empty union–find data structure with {@code n} sites
18 | * {@code 0} through {@code n-1}. Each site is initially in its own
19 | * component.
20 | *
21 | * @param n the number of sites
22 | * @throws IllegalArgumentException if {@code n < 0}
23 | */
24 | public UF(int n) {
25 | if (n < 0) throw new IllegalArgumentException();
26 | count = n;
27 | parent = new int[n];
28 | rank = new byte[n];
29 | for (int i = 0; i < n; i++) {
30 | parent[i] = i;
31 | rank[i] = 0;
32 | }
33 | }
34 |
35 | /**
36 | * Returns the component identifier for the component containing site {@code p}.
37 | *
38 | * @param p the integer representing one site
39 | * @return the component identifier for the component containing site {@code p}
40 | * @throws IndexOutOfBoundsException unless {@code 0 <= p < n}
41 | */
42 | public int find(int p) {
43 | validate(p);
44 | while (p != parent[p]) {
45 | parent[p] = parent[parent[p]]; // path compression by halving
46 | p = parent[p];
47 | }
48 | return p;
49 | }
50 |
51 | /**
52 | * Returns the number of components.
53 | *
54 | * @return the number of components (between {@code 1} and {@code n})
55 | */
56 | public int count() {
57 | return count;
58 | }
59 |
60 | /**
61 | * Returns true if the the two sites are in the same component.
62 | *
63 | * @param p the integer representing one site
64 | * @param q the integer representing the other site
65 | * @return {@code true} if the two sites {@code p} and {@code q} are in the same component;
66 | * {@code false} otherwise
67 | * @throws IndexOutOfBoundsException unless
68 | * both {@code 0 <= p < n} and {@code 0 <= q < n}
69 | */
70 | public boolean connected(int p, int q) {
71 | return find(p) == find(q);
72 | }
73 |
74 | /**
75 | * Merges the component containing site {@code p} with the
76 | * the component containing site {@code q}.
77 | *
78 | * @param p the integer representing one site
79 | * @param q the integer representing the other site
80 | * @throws IndexOutOfBoundsException unless
81 | * both {@code 0 <= p < n} and {@code 0 <= q < n}
82 | */
83 | public void union(int p, int q) {
84 | int rootP = find(p);
85 | int rootQ = find(q);
86 | if (rootP == rootQ) return;
87 |
88 | // make root of smaller rank point to root of larger rank
89 | if (rank[rootP] < rank[rootQ]) parent[rootP] = rootQ;
90 | else if (rank[rootP] > rank[rootQ]) parent[rootQ] = rootP;
91 | else {
92 | parent[rootQ] = rootP;
93 | rank[rootP]++;
94 | }
95 | count--;
96 | }
97 |
98 | // validate that p is a valid index
99 | private void validate(int p) {
100 | int n = parent.length;
101 | if (p < 0 || p >= n) {
102 | throw new IndexOutOfBoundsException("index " + p + " is not between 0 and " + (n-1));
103 | }
104 | }
105 | }
106 |
107 | /**
108 | * An Edge object is used to organize the solution to this problem
109 | * and make it easy to sort edges using a Comparator.
110 | */
111 | public static class Edge {
112 | int vert_a;
113 | int vert_b;
114 | int weight;
115 | int cost;
116 |
117 | /**
118 | * Constructor for Edge.
119 | *
120 | * @param a is the first vertex of the edge.
121 | * @param b is the second vertex of the edge.
122 | * @param w is the weight of the edge.
123 | */
124 | public Edge(int a, int b, int w) {
125 | vert_a = a;
126 | vert_b = b;
127 | weight = w;
128 | }
129 |
130 | public int get_a() {
131 | return vert_a;
132 | }
133 |
134 | public int get_b() {
135 | return vert_b;
136 | }
137 |
138 | public int get_weight() {
139 | return weight;
140 | }
141 | }
142 |
143 | /**
144 | * Implementation of a Comparator so that two edges can be
145 | * compared. Used for sorting.
146 | */
147 | public static class EdgeComparator implements Comparator {
148 | @Override
149 | public int compare(Edge a, Edge b) {
150 | if (a.get_weight() > b.get_weight())
151 | return 1;
152 | return -1;
153 | }
154 | }
155 |
156 | public static void main(String[] args) {
157 | /* Enter your code here. Read input from STDIN. Print output to STDOUT. Your class should be named Solution. */
158 |
159 | Scanner in = new Scanner(System.in);
160 |
161 | int station_count = in.nextInt(); // The number of stations.
162 | int rows = in.nextInt(); // The number of edges.
163 | int min_cost = 0;
164 | ArrayList edges = new ArrayList();
165 | UF groupings = new UF(station_count);
166 |
167 | // Scan in and create all edges.
168 | for (int i = 0; i < rows; i++) {
169 | int a = in.nextInt();
170 | int b = in.nextInt();
171 | int w = in.nextInt();
172 | Edge n = new Edge(a, b, w, 0);
173 |
174 | edges.add(n);
175 | }
176 |
177 | // Sort edges in increasing order by length.
178 | Collections.sort(edges, new EdgeComparator());
179 |
180 | // Use UnionFind to pick the set of edges that reaches the destination with minimal cost.
181 | for (int i = 0; i < edges.size(); i++) {
182 | // If a path already exists, end the loop.
183 | if (groupings.connected(0, station_count - 1))
184 | break;
185 |
186 | Edge next = edges.get(i);
187 |
188 | if (!groupings.connected(next.get_a() - 1, next.get_b() - 1)) {
189 | min_cost = next.get_weight();
190 | groupings.union(next.get_a() - 1, next.get_b() - 1);
191 | }
192 | }
193 |
194 | // If a path exists to the destination, success, otherwise it fails.
195 | if (min_cost == 0 || !groupings.connected(0, station_count - 1))
196 | System.out.println("NO PATH EXISTS");
197 | else
198 | System.out.println(min_cost);
199 | }
200 | }
201 |
--------------------------------------------------------------------------------
/Guide/GraphTheory/Journey to the Moon/README.md:
--------------------------------------------------------------------------------
1 | # Journey to the Moon
2 | This problem comes from [HackerRank](https://www.hackerrank.com/challenges/journey-to-the-moon)
3 |
4 | Category: Graph Theory
5 |
6 | Difficulty: Medium
7 |
8 | ## Problem
9 |
10 | ### Overview
11 | Given 'N' objects numbered from 0 to 'N' - 1 and 'I' pairs taken from those 'N' objects.
12 | - Determine which of the objects are grouped together.
13 | - A grouping is formed through pairs.
14 | - For example, if 1, 2, and 3 are objects and there are two pairs (1,2) and (2,3), then all three objects are in the same group even though 1 and 3 aren't directly connected.
15 | - Compute the number of ways that a pair of objects from different groups can be picked.
16 |
17 | ### Input Format
18 | - The first line contains two integers 'N' and 'I' separated by a space.
19 | - The next 'I' lines contain two integers 'A' and 'B' (in this order) each separated by a space.
20 | - 'A' and 'B' are both objects that are paired.
21 |
22 | ### Constraints
23 | - 1 <= N <= 10^5
24 | - 1 <= I <= 10^4
25 |
26 | ### Output Format
27 | - A single line with the computed value.
28 |
29 | ## Algorithm
30 |
31 | ### Overview
32 | The core of this solution is the adjacency list that holds pair data.
33 | Given this input:
34 |
35 | 5 2
36 |
37 | 0 2
38 |
39 | 1 2
40 |
41 | The adjacency list should look like this:
42 |
43 | | 0 | 1 | 2 | 3 | 4 |
44 | | --- | --- | --- | --- | --- |
45 | | 2 | 2 | 0 | _ | _ |
46 | | _ | _ | 1 | _ | _ |
47 |
48 | In order to solve this problem, one must first figure out which objects are in a group together and how large the groups are.
49 | The size of the groups is vital, because this problem ultimately boils down to combinations, which can be determined through the multiplication of different group sizes.
50 | For instance, in the above example there are three groups with sizes 3, 1, and 1 respectively.
51 | Order doesn’t matter, so the method for determining the number of ways there are to pick pairs is as follows:
52 |
53 | 3 * (1 + 1) + 1 * (1) = 7
54 |
55 | Or more generally:
56 |
57 | Group 1 * (Group 2 + Group 3) + Group 2 * (Group 1)
58 |
59 | There are three requirements for determining the size of a given group.
60 | - A counter to store the size.
61 | - A hash map to keep track of which objects have already been accounted for.
62 | - A stack to keep track of which object entries in the adjacency list still need to be visited.
63 |
64 | In order to prevent an infinite loop, values must be removed from the adjacency list after they are operated on.
65 | But this creates an issue in that groups with only a single object in them appear to be empty according to the adjacency list.
66 | So before doing operations on the adjacency list, one must first iterate through it and create a new group of size one for every empty entry.
67 |
68 | ### Pseudo Code
69 | Given an adjacency list 'pairs' implemented using a 2D vector, a vector 'countries' that will contain object group sizes, a variable 'numAsts' that contains the number of objects, and a variable 'result' that stores the number of ways a pair can be chosen.
70 | - The first dimension of 'pairs' contains an entry corresponding to each of the N objects.
71 | - The second dimension of 'pairs' contains all objects that the given object is paired with.
72 | - For each entry in 'pairs' that is empty, push a value of 1 to 'countries.'
73 | - For each entry in 'pairs.'
74 | - If the entry is not empty.
75 | - Set the counter 'countryAsts' to 0.
76 | - Create a hashMap 'tempMap.'
77 | - Create a vector 'targetAsts.'
78 | - Add the current entry to 'targetAsts.'
79 | - Add the current entry to 'tempMap.'
80 | - Add 1 to 'countryAsts.'
81 | - While 'targetAsts' isn't empty.
82 | - Pop the last element of 'targetAsts' into 'current.'
83 | - While the entry corresponding to 'current' isn't empty.
84 | - Pop the last element of the entry corresponding to 'current' into 'tempAst.'
85 | - If 'tempAst' isn't in 'tempMap.'
86 | - Add 'tempAst' to 'targetAsts.'
87 | - Add 'tempAsp' to 'tempMap.'
88 | - Increment 'countryAsts' by 1.
89 | - Add 'countryAsts' to 'countries.'
90 | - For each element in 'countries.'
91 | - Subtract the current element from 'numAsts.'
92 | - Add the product of 'numAsts' and the current element.
93 |
94 | ### Analysis
95 | This algorithm runs in linear time.
96 | There are two simple loops that contain only constant time operations, the loop that searches for single object groups and the loop that calculates 'result.'
97 | While the portion of the algorithm that calculates group sizes does feature a loop containing nested loops, it visits each value in 'pairs' a constant number of times.
98 | Given that 'pairs' contains 'I' * 2 values, it can be considered a linear time operation.
99 |
100 | ## Conclusion
101 | This problem is particularly good at highlighting the importance of not focusing on the most obvious parts of a solution.
102 | For instance, the last step is calculating the number of possible unique pairs, an operation that can be accomplished with four lines of code.
103 | Because of its simplicity, it is easy to code the last step without thinking about the correct method to use.
104 | Given a list of group sizes, the naive method involves adding the product of a given element and all other elements until the end of the list, for each element in the list.
105 | This results in an O(G^2) operation, where G is the number of groups.
106 | This is far inferior to the method shown in this solution, which is an O(G) operation.
107 |
--------------------------------------------------------------------------------
/Guide/GraphTheory/Journey to the Moon/solution.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include