I was solving a problem that asked me to operate a double subscripted array by using a single-subscripted array. Hence, the question is: how can a double-subscripted array be transformed into a single-subscripted array? or if it can't be transformed.. How can you operate a double-subscripted through a single-subscripted array?
For example:
int matrix[ m ][ n ];
//How can you transform matrix into array? Or operate it?
int array[ m * n ];
Basically, the problem asks this: "Create a class DoubleSubscriptedArray. At construction time, the class should be able to create an array of any number of rows and any number of columns.The underlying representation of the double-subscripted array should be a single-subscripted array of integers with rows * columns number of elements"
Your matrix is stored as m times n elements contiguously in memory. What you can do is interpret the first element of your matrix as a int*, and you have your array. It prevents copying the elements.
int main()
{
int matrix[3][3] = { {1, 0, 0}, {0, 1, 0}, {0, 0, 1} };
int* array = &matrix[0][0];
// int array[9] = {1, 0, 0, 0, 1, 0, 0, 0, 1}
return 0;
}
If you need to copy your elements, you can try
#include <memory>
int main()
{
int matrix[3][3] = { {1, 0, 0}, {0, 1, 0}, {0, 0, 1} };
int array[9];
std::memcpy(&array[0], &matrix[0][0], sizeof(array));
// int array[9] = {1, 0, 0, 0, 1, 0, 0, 0, 1}
return 0;
}
The simplest answer:
int array[m * n];
for (int y = 0; y < n; ++y) {
for (int x = 0; x < m; ++x) {
array[y * m + x] = matrix[x][y];
}
}
Where:
y - row number
x - column number
Now you need to serialize all rows into one:
row_no/col_no | 0 | 1 | 2 |
______________|___|___|___|
0 | 1 | 2 | 3 | <-- matrix data
1 | 4 | 5 | 6 |
||
\ /
\/
array_no 0 1 2 3 4 5
| | | | | |
[ 1, 2, 3, 4, 5, 6 ] <-- array data
array_no = row_no * number_of_rows + col_no
You can TEST it :)
P.S You can also do it like this:
int* array = (int*)matrix;
It is version without copying :)
You can recalculate index of one dimension array to store the coresponding value of two dimensional array.
If you need to copy, eficient approuch would be to copy raw by row from two dim array to one dim, cause multidimensional arrays are stored in raw mayor order,
and index can be calculated as
oneDimIndex = row*n+col
where you are fetching element at matrix[row,col]
And after, you can retrieve content from one dimension array with same calculation.
Related
Given an integer array A of size N, find minimum sum of K non-neighboring entries (entries cant be adjacent to one another, for example, if K was 2, you cant add A[2], A[3] and call it minimum sum, even if it was, because those are adjacent/neighboring to one another), example:
A[] = {355, 46, 203, 140, 28}, k = 2, result would be 74 (46 + 28)
A[] = {9, 4, 0, 9, 14, 7, 1}, k = 3, result would be 10 (9 + 0 + 1)
The problem is somewhat similar to House Robber on leetcode, except instead of finding maximum sum of non-adjacent entries, we are tasked to find the minimum sum and with constraint K entries.
From my prespective, this is clearly a dynamic programming problem, so i tried to break down the problem recursively and implemented something like this:
#include <vector>
#include <iostream>
using namespace std;
int minimal_k(vector<int>& nums, int i, int k)
{
if (i == 0) return nums[0];
if (i < 0 || !k) return 0;
return min(minimal_k(nums, i - 2, k - 1) + nums[i], minimal_k(nums, i - 1, k));
}
int main()
{
// example above
vector<int> nums{9, 4, 0, 9, 14, 7, 1};
cout << minimal_k(nums, nums.size() - 1, 3);
// output is 4, wrong answer
}
This was my attempt at the solution, I have played around a lot with this but no luck, so what would be a solution to this problem?
This line:
if (i < 0 || !k) return 0;
If k is 0, you should probably return return 0. But if i < 0 or if the effective length of the array is less than k, you probably need to return a VERY LARGE value such that the summed result goes higher than any valid solution.
In my solution, I have the recursion return INT_MAX as a long long when recursing into an invalid subset or when k exceeds the remaining length.
And as with any of these dynamic programming and recursion problems, a cache of results so that you don't repeat the same recursive search will help out a bunch. This will speed things up by several orders of magnitude for very large input sets.
Here's my solution.
#include <iostream>
#include <vector>
#include <unordered_map>
#include <algorithm>
using namespace std;
// the "cache" is a map from offset to another map
// that tracks k to a final result.
typedef unordered_map<size_t, unordered_map<size_t, long long>> CACHE_MAP;
bool get_cache_result(const CACHE_MAP& cache, size_t offset, size_t k, long long& result);
void insert_into_cache(CACHE_MAP& cache, size_t offset, size_t k, long long result);
long long minimal_k_impl(const vector<int>& nums, size_t offset, size_t k, CACHE_MAP& cache)
{
long long result = INT_MAX;
size_t len = nums.size();
if (k == 0)
{
return 0;
}
if (offset >= len)
{
return INT_MAX; // exceeded array boundary, return INT_MAX
}
size_t effective_length = len - offset;
// If we have more k than remaining elements, return INT_MAX to indicate
// that this recursion is invalid
// you might be able to reduce to checking (effective_length/2+1 < k)
if ( (effective_length < k) || ((effective_length == k) && (k != 1)) )
{
return INT_MAX;
}
if (get_cache_result(cache, offset, k, result))
{
return result;
}
long long sum1 = nums[offset] + minimal_k_impl(nums, offset + 2, k - 1, cache);
long long sum2 = minimal_k_impl(nums, offset + 1, k, cache);
result = std::min(sum1, sum2);
insert_into_cache(cache, offset, k, result);
return result;
}
long long minimal_k(const vector<int>& nums, size_t k)
{
CACHE_MAP cache;
return minimal_k_impl(nums, 0, k, cache);
}
bool get_cache_result(const CACHE_MAP& cache, size_t offset, size_t k, long long& result)
{
// effectively this code does this:
// result = cache[offset][k]
bool ret = false;
auto itor1 = cache.find(offset);
if (itor1 != cache.end())
{
auto& inner_map = itor1->second;
auto itor2 = inner_map.find(k);
if (itor2 != inner_map.end())
{
ret = true;
result = itor2->second;
}
}
return ret;
}
void insert_into_cache(CACHE_MAP& cache, size_t offset, size_t k, long long result)
{
cache[offset][k] = result;
}
int main()
{
vector<int> nums1{ 355, 46, 203, 140, 28 };
vector<int> nums2{ 9, 4, 0, 9, 14, 7, 1 };
vector<int> nums3{8,6,7,5,3,0,9,5,5,5,1,2,9,-10};
long long result = minimal_k(nums1, 2);
std::cout << result << std::endl;
result = minimal_k(nums2, 3);
std::cout << result << std::endl;
result = minimal_k(nums3, 3);
std::cout << result << std::endl;
return 0;
}
It is core sorting related problem. To find sum of minimum k non adjacent elements requires minimum value elements to bring next to each other by sorting. Let's see this sorting approach,
Given input array = [9, 4, 0, 9, 14, 7, 1] and k = 3
Create another array which contains elements of input array with indexes as showed below,
[9, 0], [4, 1], [0, 2], [9, 3], [14, 4], [7, 5], [1, 6]
then sort this array.
Motive behind this element and index array is, after sorting information of index of each element will not be lost.
One more array is required to keep record of used indexes, so initial view of information after sorting is as showed below,
Element and Index array
..............................
| 0 | 1 | 4 | 7 | 9 | 9 | 14 |
..............................
2 6 1 5 3 0 4 <-- Index
Used index record array
..............................
| 0 | 0 | 0 | 0 | 0 | 0 | 0 |
..............................
0 1 2 3 4 5 6 <-- Index
In used index record array 0 (false) means element at this index is not included yet in minimum sum.
Front element of sorted array is minimum value element and we include it for minimum sum and update used index record array to indicate that this element is used, as showed below,
font element is 0 at index 2 and due to this set 1(true) at index 2 of used index record array showed below,
min sum = 0
Used index record array
..............................
| 0 | 0 | 1 | 0 | 0 | 0 | 0 |
..............................
0 1 2 3 4 5 6
iterate to next element in sorted array and as you can see above it is 1 and have index 6. To include 1 in minimum sum we have to find, is left or right adjacent element of 1 already used or not, so 1 has index 6 and it is last element in input array it means we only have to check if value of index 5 is already used or not, and this can be done by looking at used index record array, and as showed above usedIndexRerocd[5] = 0 so 1 can be considered for minimum sum. After using 1, state updated to following,
min sum = 0 + 1
Used index record array
..............................
| 0 | 0 | 1 | 0 | 0 | 0 | 1 |
..............................
0 1 2 3 4 5 6
than iterate to next element which is 4 at index 1 but this can not be considered because element at index 0 is already used, same happen with elements 7, 9 because these are at index 5, 3 respectively and adjacent to used elements.
Finally iterating to 9 at index = 0 and by looking at used index record array usedIndexRecordArray[1] = 0 and that's why 9 can be included in minimum sum and final state reached to following,
min sum = 0 + 1 + 9
Used index record array
..............................
| 1 | 0 | 1 | 0 | 0 | 0 | 1 |
..............................
0 1 2 3 4 5 6
Finally minimum sum = 10,
One of the Worst case scenario when input array is already sorted then at least 2*k - 1 elements have to be iterated to find minimum sum of non adjacent k elements as showed below
input array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] and k = 4 then following highlighted elements shall be considered for minimum sum,
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Note: You have to include all input validation, like one of the validation is, if you want to find minimum sum of k non adjacent elements then input should have at least 2*k - 1 elements. I am not including these validations because i am aware of all input constraints of problem.
#include <iostream>
#include <vector>
#include <algorithm>
using std::cout;
long minSumOfNonAdjacentKEntries(std::size_t k, const std::vector<int>& arr){
if(arr.size() < 2){
return 0;
}
std::vector<std::pair<int, std::size_t>> numIndexArr;
numIndexArr.reserve(arr.size());
for(std::size_t i = 0, arrSize = arr.size(); i < arrSize; ++i){
numIndexArr.emplace_back(arr[i], i);
}
std::sort(numIndexArr.begin(), numIndexArr.end(), [](const std::pair<int, std::size_t>& a,
const std::pair<int, std::size_t>& b){return a.first < b.first;});
long minSum = numIndexArr.front().first;
std::size_t elementCount = 1;
std::size_t lastIndex = arr.size() - 1;
std::vector<bool> usedIndexRecord(arr.size(), false);
usedIndexRecord[numIndexArr.front().second] = true;
for(std::vector<std::pair<int, std::size_t>>::const_iterator it = numIndexArr.cbegin() + 1,
endIt = numIndexArr.cend(); elementCount < k && endIt != it; ++it){
bool leftAdjacentElementUsed = (0 == it->second) ? false : usedIndexRecord[it->second - 1];
bool rightAdjacentElementUsed = (lastIndex == it->second) ? false : usedIndexRecord[it->second + 1];
if(!leftAdjacentElementUsed && !rightAdjacentElementUsed){
minSum += it->first;
++elementCount;
usedIndexRecord[it->second] = true;
}
}
return minSum;
}
int main(){
cout<< "k = 2, [355, 46, 203, 140, 28], min sum = "<< minSumOfNonAdjacentKEntries(2, {355, 46, 203, 140, 28})
<< '\n';
cout<< "k = 3, [9, 4, 0, 9, 14, 7, 1], min sum = "<< minSumOfNonAdjacentKEntries(3, {9, 4, 0, 9, 14, 7, 1})
<< '\n';
}
Output:
k = 2, [355, 46, 203, 140, 28], min sum = 74
k = 3, [9, 4, 0, 9, 14, 7, 1], min sum = 10
I have the following array:
{7, 1, 3, 9, 5, 4, 7, 8, 2}
and a empty n-size array. Now I want to find the index of the n-least values in that given array without sorting and write them to the empty array. For example n = 3:
{1, 8, 2}
Is there an easy way to do that?
If you are not restricted in sorting other arrays, then create an array of indices and sort the array of indices in accordance with the original array.
#include <vector>
#include <iostream>
#include <algorithm>
#include <numeric>
int main()
{
int n = 3;
// test data
std::vector<int> test = { 7, 1, 3, 9, 5, 4, 7, 8, 2 };
// index array
std::vector<int> index(test.size());
// set the index array to 0, 1, 2, … n-1
std::iota(index.begin(), index.end(), 0);
// sort the index array
std::sort(index.begin(), index.end(), [&](int n1, int n2) { return test[n1] < test[n2]; });
// output results -- note we are printing the index array
for (int i = 0; i < n; ++i)
std::cout << index[i] << "\n";
}
Output:
1
8
2
Start with first value in array.
Compare the values from the array and the value of the index in the n-least array. (If empty then just add it).
If the value is less, then shift the array from that position and add the index to that position in the n-least array.
If it's not less then compare the next value from the n-least array and so forth.
This is probably not optimal but atleast it's not of O(n^2) complexity that a naive solution would yield.
I'll write this in pseudo code:
n = 3
arr = [7, 1, 3, 9, 5, 4, 7, 8, 2]
narr = []
for i as 0 to sizeof(arr) - 1
for j as 0 to n - 1
if narr[j] is undefined or arr[i] < arr[narr[j]]
narr.shiftRight(j, 1)
narr[j] = i;
break
endif
endfor
endfor
I have an vector<int> number_vector that contains {1, 0, 0, 0, 0, 0 ,0}. I need to iterate over this number_vector, e.g 4 times, and remove the first smallest number at each iteration, i.e at the first iteration I will remove the value 0 at the index 1, at the next iteration I will remove the 0 that is at the index 1, etc. I'm doing this right now the following way:
int n = 7;
int d = 4;
vector<int> number_vector{1, 0, 0, 0, 0, 0 ,0};
for (int counter = 0; counter < n - d; counter++)
{
int index = distance(number_vector.begin(), min_element(number_vector.begin(), number_vector.end()));
if (index != number_vector.size() - 1)
{
number_vector[index] = move(number_vector.back());
}
number_vector.pop_back();
// number_vector.erase(number_vector.begin() + index);
}
The problem it's that if I run the code above, at the end number_vector has {1, 0, 0, 0} while it should have {1, 0, 0}, and for other cases like n = 4, d = 2 and number_vector{3, 7, 5, 9}, the final number_vector has the right value, that is 79. Some tips?
First of all you're iterating three times, not four. Secondly, if the vector isn't required, you can just use a map and pop the front iterator since it will always be the lowest value. Finally, there is no need for a swap or distance, just erase the result of min_element if it's not invalid.
When you iterate from 0 to n-d, with n=7 and d=4. you will iterate from counter=0 to counter < 7-4, i.e., 3. So your loop will iterate 3 times with values 0, 1 and 2. This will remove three zeros from number_vector. So your code is behaving as expected.
I think what you want is to iterate from 0 to d. Also you are unnecessarily complicating the code by using index. You can use the iterator directly like below.
for (int counter = 0; counter < d; counter++)
{
*min_element(number_vector.begin(), number_vector.end()) = *number_vector.rbegin();
number_vector.pop_back();
}
Is your d represents the times of pop minimum number from vector?
Then modify counter < n - d to counter < d, it will have {1, 0, 0}
11.04
if you want to keep the order,you can modify
for (int counter = 0; counter < d; ++counter)
{
auto iter = min_element(number_vector.begin(), number_vector.end());
number_vector.erase(iter);
}
PS:std::list maybe a better choice?
I have my large sparse symmetric matrix stored as Compressed Sparse Row (CSR) using Intel MKL. For the sake of example, let's assume my symmetric sparse matrix is a 5x5:
A =
1 -1 0 -3 0
-1 5 0 0 0
0 0 4 6 4
-3 0 6 7 0
0 0 4 0 -5
values = {1, -1, -3, 5, 4, 6, 4, 7, -5}; // symmetric sparse matrix
columns = {0, 1, 3, 1, 2, 3, 4, 3, 4}; // zero-based
rowIndex = {0, 3, 4, 7, 8, 9}; // zero-based
I am trying to find a submatrix of A given the rows and columns, e.g., A(1:3, 2:4):
A(1:3,2:4) =
0 0 0
4 6 4
6 7 0
values = {4, 6, 4, 6, 7}; // General sparse matrix (sub-matrix is not necessarily symmetric)
columns = {0, 1, 2, 0, 1}; // zero-based
rowIndex = {0, 0, 3, 5}; // zero-based
I would be grateful to know how matrix-indexing can be done. One way I can think of is to convert CSR to coordinate format COO and apply matrix-indexing and then converting it back to CSR, which I don't think it is an efficient way.
Could someone let me know of an efficient or a common way of sparse matrix-indexing?
The trick is to look up values in the lower triangle by the output column (which is their row). You can keep an index into the data for each row, since you visit the entries in column order as you progress in row order for the output.
With the expositional type
struct CSR { // sometimes implicitly symmetric
std::vector<...> vals;
std::vector<int> cols,rowStart;
};
we have
// Return the [r0,r1) by [c0,c1) submatrix, never
// using any symmetry it might have.
CSR submatrix(const CSR &sym,int r0,int r1,int c0,int c1) {
const int m=r1-r0,n=c1-c0;
std::vector<int> finger(sym.rowStart.begin()+c0,sym.rowStart.begin()+c1);
CSR ret;
ret.rowStart.reserve(m+1);
ret.rowStart.push_back(0);
for(int r=0,rs=r0;r<m;++r,++rs) {
// (Strictly) lower triangle:
for(int cs=c0,c=0;cs<rs;++cs,++c)
for(int &f=finger[c],f1=sym.rowStart[cs+1];f<f1;++f) {
const int cf=sym.cols[f];
if(cf>rs) break;
if(cf==rs) {
ret.vals.push_back(sym.vals[f]);
ret.cols.push_back(c);
}
}
// Copy the relevant subsequence of the upper triangle:
for(int f=sym.rowStart[rs],f1=sym.rowStart[rs+1];f<f1;++f) {
const int c=sym.cols[f]-c0;
if(c<0) continue;
if(c>=n) break;
ret.vals.push_back(sym.vals[f]);
ret.cols.push_back(c);
}
ret.rowStart.push_back(ret.vals.size());
}
return ret;
}
For large matrices, the upper triangle loop could be optimized by using a binary search to find the relevant range of f.
This question already has answers here:
Sorting zipped (locked) containers in C++ using boost or the STL
(5 answers)
Closed 8 years ago.
Consider the case where “rowPtr”, “colInd” and “values” in a struct are dynamically allocated with same number of elements. In this scenario, what is the fastest way (without copying if possible!!) to sort elements of colInd so that rowPtr and value elements are swapped or change positions based on how elements of colInd change positions.
struct csr
{
int rows;
int cols;
int nzmax;
int *rowPtr;
int *colInd;
double *values;
};
// A simple example without a struct. Just based on arrays
double values[10] = {0.2135, 0.8648, 7, 0.3446, 0.1429, 6, 0.02311, 0.3599, 0.0866, 8 };
int rowPtr[10] = { 0, 3, 6, 10, 2 -1, 24, -4, 1, 11 };
int colInd[10] = { 0, 2, 4, 1, 2, 3, 0, 1, 2, 4 };
// sort colInd and simultaneously change positions in rowPtr and values
//After sorting
Values = {0.214, 0.023, 0.345, 0.360, 0.865, 0.143, 0.087, 6.0};
rowPtr = {0, 24, 10, -4, 3, 2, 1, -1};
colInd = {0, 0, 1, 1, 2, 2, 2, 3};
I suggest putting the three arrays into an array of struct and sorting the array of struct.
struct csr_data
{
int rowPtr;
int colInd;
double value;
};
and
struct csr
{
int rows;
int cols;
int nzmax;
csr_data* data_array;
};
You can sort an array of csr_data using any of the three member variables. When they are sorted, all elements of csr_data will be rearranged regardless of which member you use to sort the data by.