Related
I am looking at this Gold mine problem.
Given a gold mine of n*m dimensions. Each field in this mine contains a positive integer which is the amount of gold in tons. Initially the miner is at first column but can be at any row. He can move only (right->,right up /,right down) that is from a given cell, the miner can move to the cell diagonally up towards the right or right or diagonally down towards the right. Find out maximum amount of gold he can collect.
Examples:
Input : mat[][] = {{1, 3, 3},
{2, 1, 4},
{0, 6, 4}};
Output : 12
{(1,0)->(2,1)->(1,2)}
Input: mat[][] = { {1, 3, 1, 5},
{2, 2, 4, 1},
{5, 0, 2, 3},
{0, 6, 1, 2}};
Output : 16
(2,0) -> (1,1) -> (1,2) -> (0,3) OR
(2,0) -> (3,1) -> (2,2) -> (2,3)
This is the working code:
class GFG {
static final int MAX = 100;
static int getMaxGold(int gold[][],
int m, int n)
{
int goldTable[][] = new int[m][n];
for (int col = n-1; col >= 0; col--)
{
for (int row = 0; row < m; row++)
{
int right = (col == n-1) ? 0
: goldTable[row][col+1];
int right_up = (row == 0 ||
col == n-1) ? 0 :
goldTable[row-1][col+1];
int right_down = (row == m-1
|| col == n-1) ? 0 :
goldTable[row+1][col+1];
goldTable[row][col] = gold[row][col]
+ Math.max(right, Math.max(right_up,
right_down));
}
}
int res = goldTable[0][0];
for (int i = 1; i < m; i++)
res = Math.max(res, goldTable[i][0]);
return res;
}
}
I understood this program clearly. But this code starts the for loop from last column col = n-1, so how can solve this task if I am starting from first column instead of last:
for (int col = 0; col <n; col++)
{
for (int row = 0; row < m; row++)
{
}
}
Is it possible to solve this problem if we start from first row and first column?
Hello there smart people.
I have a following graph problem.
Given a complete, directed, wieghted graph with n vertices, find the length of the shortest path (starting at any vertex) going through m - 1 edges (edges in the path might repeat).
As for the limits n <= 200, m <= 1e9.
Looking at the limits I can say there must be some clever way without some sort of dp and graph traversing but I just cant think of anything like that.
Thanks in advance.
Example:
n = 3, m = 5
edges:
1 -> 2 weight = 10,
1 -> 3 weight = 100,
2 -> 1 weight = 10,
2 -> 3 weight = 50,
3 -> 1 weight = 30,
3 -> 2 weight = 70,
answer would be 40 (1 -> 2 -> 1 -> 2 -> 1)
A naive solution would be to run BFS (breadth-first search) until the mth level and maintain the minimum sum of weights and return it.
But in the question it says we can include the vertex as many times till there is a path between them, so now we can do the below steps:
Calculate all the cycles present in the graph, we can reuse these cycles in calculating the minimum weight possible.
for example:
in the question, there is a cycle present 1-->2-->1 of length=3 weight=20, the value of m = 5, now we can use this path twice, but if m was 6 then we are left with 1 more node to include.
Now we can calculate the min path (to include leftover nodes) of length l (which is 1 if m=6) from 1 and add it to the above weight. (which will we 1-->2 =10)
Repeat the steps 1 and 2 for every cycle present in the graph and maintain the minimum sum.
Below is the c++ code describing the above solution (it may not be 100% correct, but you will get the basic idea)
#include <iostream>
#include <queue>
#include <vector>
using namespace std;
struct Edge{
int src, dest, weight;
};
struct Node{
int start_vertex, end_vertex, weight, edge_count=0;
};
class Graph{
public:
vector<vector<pair<int, int>>> adjList;
int V;
Graph(vector<Edge> edges, int V){
adjList.resize(V+1);
this->V = V;
for(Edge edge:edges){
adjList[edge.src].push_back({edge.dest, edge.weight});
}
}
};
int BFS(Graph &g, int m){
queue<Node> Q;
vector<Node> cycles;
// to store min path from vertex i of length j
vector<vector<int>> dp(g.V+1, vector<int>(g.V+1, INT_MAX));
for(int i=0; i<=g.V; i++)
dp[i][0] = 0;
for(int i=1; i<=g.V; i++){
Q.push({i, i, 0, 1});
}
while(!Q.empty()){
Node top = Q.front();
Q.pop();
if(top.edge_count >= g.V) break;
int v = top.end_vertex;
int start_vertex = top.start_vertex;
int weight = top.weight;
int edge_count = top.edge_count;
for(auto x:g.adjList[v]){
// finding all the cycles
if(x.first == start_vertex){
Node n = {start_vertex, v, weight+x.second, edge_count+1};
cycles.push_back(n);
}else{
Q.push({start_vertex, x.first, weight+x.second, edge_count+1});
}
if(dp[start_vertex][edge_count] > weight+x.second){
dp[start_vertex][edge_count] = weight+x.second;
}
}
}
// finding minimum:
int min_weight = INT_MAX;
if(m<=g.V){
for(int i=1; i<=g.V; i++){
min_weight = min(min_weight, dp[i][m]);
}
}
// checking all the cycles for reusability and maintaining min sum
for(int i=0; i<cycles.size(); i++){
int sum = cycles[i].weight;
int length_left_to_cover = m-cycles[i].edge_count;
sum += length_left_to_cover/(cycles[i].edge_count-1) * cycles[i].weight;
int vertices_left_to_include = 0;
if(m-cycles[i].edge_count>0){
vertices_left_to_include = (m-cycles[i].edge_count)%(cycles[i].edge_count-1);
}
min_weight = min(min_weight, sum+dp[cycles[i].start_vertex][vertices_left_to_include]);
}
return min_weight;
}
// 1 -> 2 weight = 10,
// 1 -> 3 weight = 100,
// 2 -> 1 weight = 10,
// 2 -> 3 weight = 50,
// 3 -> 1 weight = 30,
// 3 -> 2 weight = 70,
int main(){
vector<Edge> edges = {
{1, 2, 10},
{1, 3, 100},
{2, 1, 10},
{2, 3, 50},
{3, 1, 30},
{3, 2, 70}
};
int V = 3;
int m = 5;
Graph g(edges, V);
cout<<"Min weight: "<<BFS(g, m);
}
Output:
Min weight: 40
How to find triplets, form an array ,
(X1, X2, Y),
such that
X1 * X2 = Y2
There can't be any repetition in the result and the elements are in a range of 105
I have tried doing it, by taking all combinations, but I want an efficient approach ...
Because a number Y <= 100000 can have at most 6 distinct prime factors, each Y2 will have less than 4064 factor pairs. On average, about 100.
That leads to an O(N) algorithm... It has a factor of x000 in it, but it will still be faster than the O(N2) solutions for large inputs:
Build a hashmap that gives the frequency for each number in the array (O(N))
For each number Y, completely factorize it, and generate each possible pair of factors for Y2. To factorize Y, trial division by primes less than 316 is fine.
For each pair, check the frequency table to see if they both appear in addition to Y. Note that Y is a factor of Y2, and for this one you have to check to see if Y appears at least 3 times.
Also, you only need to check the keys of the hashmap, and there are at most 100000 of those. Even if every number <= 100000 is in the array, there are less than 7M factor pairs to check.
Using HashMap of Java,
taking all pairs of x1, x2 from the array and inserting into the Map as [y, [x1, x2]] only when x1*x2 is a square. That eliminates many combinations, reduces memory requirements and less comparison for the later part.
Then loop through the Map key values matching with the array elements.
This is O(n^2) timing complexity.
public class FindTriplets
{
final static int isSquare(long n)
{
int tst = (int) (Math.sqrt(n) + 0.5);
if ((tst * tst) == n)
return tst;
else
return 0;
}
static void findTriplets(int[] nums)
{
Map<Integer, List<Integer>> triplets = new HashMap<Integer, List<Integer>>();
int n = nums.length;
// insert into a Map as {y, [x1, x2]} when y*y = x1*x2, x1 & x2 are elements of nums
for (int i = 0; i < n - 1; i++)
{
for (int j = i + 1; j < n; j++)
{
int y = isSquare(nums[i] * nums[j]);
if (y != 0)
{
List<Integer> x1x2 = new ArrayList<Integer>(Arrays.asList(nums[i], nums[j]));
triplets.put(y, x1x2);
}
}
}
// Now look for elements nums[i] matching with y in the Map
for (int i = 0; i < n; i++)
{
if (triplets.containsKey(nums[i]))
{
List<Integer> x1x2 = triplets.get(nums[i]);
System.out.println(x1x2.toString() + " -> " + nums[i]);
}
}
}
public static void main(String[] args)
{
int[] num = { 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 15, 16, 18 };
findTriplets(num);
}
}
Output:
[2, 8] -> 4
[4, 9] -> 6
[4, 16] -> 8
[9, 16] -> 12
A python implementation (more compact and readable) of the Dmitry solution that cost O(N^2)
import math
input_list = [1,2,18,7,6,22,4,8,65]
squared_y = {x**2 for x in input_list} #this will be a set with O(1) lookup
solution = set()
for index, x1 in enumerate(input_list):
for x2 in input_list[index+1:]:
if x1 * x2 in squared_y:
solution.add((x1,x2))
solution.add((x2,x1))
for sol in solution:
if sol[0] <= sol[1]:
print(sol[0], sol[1], int(math.sqrt(sol[0]*sol[1])), sep=", ")
Result:
2, 18, 6
2, 8, 4
1, 4, 2
Given an array with n elements , one need to count number of subsets whose sum is greater than or equal to k.
Eg arr[] = {1,5,9,2,3}, k =16
1+5+9+2=17
1+5+9+3=18
1+5+9+2+3=20
5+9+2=16
5+9+3=17
5+9+2+3=19
Answer is 6.
One approach what i know is to use dynamic programming using bit masking and check if sum>=k and increment the count.
Problem with this approach is N should be very small since bit masking involves exponential running time.
Is there any other efficient algorithm for the above problem.
Thanks in advance.
Make array Counts[Sum+1] where Sum is sum of all elements
Set Counts[0] = 1, other elements - zero
For ever x=arr[i] scan Counts array from the end and increment those entries, that could be composed from existing so far sums and x
if Counts[j - arr[i]] > 0 then //this check might be omitted
Counts[j] = Counts[j - arr[i]] + Counts[j]
Then sum non-zero Counts entries for j>=k
Complexity is O(Sum * N)
If range of possible sums is large but number of possible sums is not so high (like arr=[1, 2, 3, 100000000, 100000001] array), you can exploit memoization approach and store only really existing variants in the map
Example:
arr=[1,2,3,5]
Counts = [1,0,0,0,0,0,0,0,0,0,0,0]
after arr[0]=1
Counts = [1,1,0,0,0,0,0,0,0,0,0,0]
after arr[1]=2
Counts = [1,1,1,1,0,0,0,0,0,0,0,0]
after arr[2]=3
Counts = [1,1,1,2,1,1,1,0,0,0,0,0]
after arr[3]=5
Counts = [1,1,1,2,1,2,2,1,2,1,1,1]
Counts[8] could be composed from 5 and existing Counts[3] with two variants
1+2+5; 3+5
One approach would be to use recursion to create the subsets and stop the recursion when the sum of the elements omitted from the original set is greater than total-k, where total is the sum of all elements of the array.
Here's some Java code that illustrates the approach:
import java.util.ArrayList;
import java.util.BitSet;
import java.util.List;
public class SubSet
{
public static void main(String[] args)
{
Integer[] set = { 1, 5, 9, 2, 3 };
List<List<Integer>> subsets = subsetsK(set, 16);
for (List<Integer> subset : subsets)
{
System.out.println(subset);
}
}
static List<List<Integer>> subsetsK(Integer[] arr, int k)
{
int t = 0;
for (int n : arr) t += n;
List<List<Integer>> subsets = new ArrayList<>();
allSubsets(subsets, arr, new BitSet(arr.length), 0, 0, t - k);
return subsets;
}
public static void allSubsets(List<List<Integer>> subsets, Integer[] arr, BitSet off, int pos, int sum, int lim)
{
if(sum > lim) return;
if(pos == arr.length)
{
subsets.add(toSubset(arr, off));
return;
}
off.set(pos);
allSubsets(subsets, arr, off, pos + 1, sum + arr[pos], lim);
off.clear(pos);
allSubsets(subsets, arr, off, pos + 1, sum, lim);
}
static List<Integer> toSubset(Integer[] arr, BitSet off)
{
List<Integer> ss = new ArrayList<>();
for (int i = 0; i < arr.length; i++)
{
if (!off.get(i))
ss.add(arr[i]);
}
return ss;
}
}
Output:
[5, 9, 3]
[5, 9, 2]
[5, 9, 2, 3]
[1, 5, 9, 3]
[1, 5, 9, 2]
[1, 5, 9, 2, 3]
You can run/edit the code here: Ideone
I am trying to flatten a two dimensional array into a one dimensional array. This is what I currently have. I would like the flatten out my array so that the one dimensional array looks like this
int[] oneDim = {1, 2, 3, 4, 5, 6, 7, 8 ,9 ,10, 11, 12};
This is what I currently have. I dont really know how to go about doing this. All help and input is appreciated.
void setup() {
int[][] twoDim = { {1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12} };
int[] oneDim = new int[twoDim.length];
for (int i = 0; i < twoDim.length; i++) {
for (int j = 0; j < twoDim[i].length; j++) {
oneDim[j] += twoDim[j][i];
}
}
println(oneDim);
}
int[][] twoDim = { {1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12} };
int x = twoDim.length;
int y = twoDim[0].length;
int[] oneDim = new int[x*y];
for (int i = 0; i < x; i++) {
for (int j = 0; j < y; j++) {
oneDim[i*y + j] = twoDim[i][j];
}
}
println(oneDim);
Here's a hint: the usual formula for mapping two dimensions to one is: width*y + x, where width is the number of elements in each row (4, in your case, as given by twoDim[i].length, assuming they are all the same length), 'x' is the iterator over columns (j, in your case), and y is the iterator over rows (i for you).
You will want to check that the size of your one dimensional array is sufficient to accept all the elements of twoDim. It doesn't look big enough as it is - it needs to be twoDim[i].length * twoDim.length elements long, at least.
You're currently writing the same row of data over and over again, because you're assigning to oneDim[j] in the inner loop for every iteration of the outer loop. Try assigning to oneDim (once it is of appropriate size) using the formula I suggested at the start of this answer instead.