I'm taking in an array of numbers [4, 6, 23, 10, 1, 3] I need to return true if any combinations of numbers in the array add up to the largest number in the array. So the example above should return true because 3 + 4 + 6 + 10 = 23
My thought behind this problem is I should first put the array in numerical order then make a new array with just the numbers I'm adding because I'm not adding the largest number. Then I need some method that says "If any combination of adding these numbers together equals the largest number in the original array return true". This is the code I've written so far, but I'm stuck on the for loop.. Any help would be very much appreciated!
function ArrayChallenge(arr){
let order = arr.sort(function(a, b){return a-b})
let addThese = order.slice(0,order.length-1)
for(i = 0; i < addThese.length-1; i++){
return true
}
}
console.log(ArrayChallenge([3,5,-1,8,12]))
It seems like a trick question. Here's the answer:
function ArrayChallenge(arr){
return true
}
Because the sum of just the largest number is always equal to the largest number.
If this solution is somehow not allowed, see subset sum problem:
there is a multiset S of integers and a target-sum T, and the question is to decide whether any subset of the integers sum to precisely T.
The most straightforward solution to that problem is with recursion; something like this:
function subsetSum(arr, sum) {
if (arr.length == 0) {
// No numbers left in the array. The only sum we can make is 0.
// If that is the sum we are seeking, great!
return sum == 0
} else {
// We will try both using and not using the first number in the array.
// The rest is passed to the recursive call.
const [current, ...remaining] = arr
return (
// Exclude current number, and recurse. We have to make the full
// sum with the remaining numbers.
subsetSum(remaining, sum) ||
// Include current number, meaning we have sum - current left
// to make with the remaining numbers.
subsetSum(remaining, sum - current)
)
}
}
Related
I am trying to solve a problem on leetCode:
Given an unsorted integer array nums, return the smallest missing positive integer.
This is the code I came up with
var firstMissingPositive = function(nums) {
nums.sort();
let x = 1; //this is to compare the elements of nums
for (let num in nums) {
if (nums[num] <= 0) continue; //because anything less than 1 does not matter
else if (nums[num] != x) break; //if x is not present, x is the answer
else x++; // if x is present, x should increment and check for the next integer
}
return x;
};
This code works 106/173 testcases. It does not pass the following case, which looks very simple -
nums = [1,2,3,4,5,6,7,8,9,20];
The output I get is 3, whereas the expected output is 10.
I'm not looking for the right solution to the problem. I'm just curious why this seemingly simple test fails. I do not understand why my loop breaks at 3 when it passes 1 and 2. Please help!
Here's the root cause of your problem (mdn):
The sort() method sorts the elements of an array in place and returns
the sorted array. The default sort order is ascending, built upon
converting the elements into strings, then comparing their sequences
of UTF-16 code units values.
So what you get after sort is [1, 2, 20, 3, ...], as '20' string precedes '3' string. One possible way to fix this it to force sorting by numeric value:
nums.sort((a, b) => a - b);
trying to figure out this coding problem:
Write an algorithm to determine if a number n is "happy".
A happy number is a number defined by the following process: Starting with any positive integer, replace the number by the sum of the squares of its digits, and repeat the process until the number equals 1 (where it will stay), or it loops endlessly in a cycle which does not include 1. Those numbers for which this process ends in 1 are happy numbers.
Return True if n is a happy number, and False if not.
I've done some work but I'm not sure what I'm doing incorrectly. Would appreciate some pointers. Thanks!
function isHappy(numba1){
let sum = 0;
numba = numba1.toString().split('')
let numbaArr = numba.map(y => parseInt(y))
for (var x = 0; x< numbaArr.length; x++){
sum += numbaArr[x] ** 2
}
if (sum > 1){
isHappy(sum)
}
else if (sum === 1){
return true
}
else if (sum <= 0){
return false
}
}
There are two problems I see with your answer, one small and one large.
Small: The value of the recursive call is not being returned. This:
if (sum > 1){
isHappy(sum)
}
should be
if (sum > 1){
return isHappy(sum)
}
Large: you are not doing the essential work of checking whether we're cycling over the same values. For instance in testing 15, we get these values
15, 26, 40, 16, 37, 58, 89, 145, 42, 20, 4, 16
^^ ^^
and we can quit because we've seen 16 twice. 15 is not happy. But for 44 we get
44, 32, 13, 10, 1
and we hit 1 without cycling, so 44 is a happy number.
Your code needs to keep track of the values it's seen so far.
Here's one recursive approach:
const digitsSquareSum = (n) =>
String (n) .split ('') .map (n => n * n) .reduce ((a, b) => a + b, 0)
const _isHappy = (n, seen) =>
n == 1
? true
: seen .has (n)
? false
: _isHappy (digitsSquareSum (n), seen .add (n))
const isHappy = (n) =>
_isHappy(n, new Set())
// display the happy numbers among the first 100 positive integers
console .log (Array .from ({length: 100}, (_, i) => i + 1) .filter (isHappy) .join(', '))
We use a helper function to calculate the sum of the squares of the digits. This simply makes the main function cleaner. The main function, _isHappy is an internal, private function, not to be exposed to the users. It is recursive and maintains a Set of the values we've already seen. If our number is 1, we return true. If our number is in the set of values we've already seen, we return false. Otherwise, we add it to the already seen set, calculate the next test case by calling our helper, and call _isHappy with those.
Our public function simply calls this main function, creating the initial empty Set of seen values, and passing that along with the number to test.
In our demo, we use Array .from ({length: 100}, (_, i) => i + 1), which is one of several compact ways of creating an array of integers from 1 to 100. In practice, I would abstract this into a range function that takes lo and hi values and creates an array of integers in between them, but that's outside the point of this answer.
We do not have to use this breakdown of an internal recursive function with two parameters and a public function with one. We could use a default parameter like this:
const isHappy = (n, seen = new Set()) =>
console .log({n, seen}) ||
n == 1
? true
: seen .has (n)
? false
: isHappy (digitsSquareSum (n), seen .add (n))
But there are some potential problems with this. For instance we could not call it like we did before:
range(1, 100) .filter (isHappy)
because filter supplies additional parameters to its callback. Not only does it supply the value but also the index and the whole array. However isHappy thinks the second parameter is the Set of seen values; when it gets passed the index, things will fail. We can do this instead:
range(1, 100) .filter ((n) => isHappy (n))
But we will always have to take such cautions when writing this way. I've gotten in the habit of doing this only for internal functions where I control how it's called. And still once in a while it bites me.
Keep a list of seen numbers and mod 10 to get the last digit then divide by 10 and floor to shift digits:
function sumSquares(num) {
let sum = 0;
while (num != 0) {
sum += (num % 10) ** 2;
num = Math.floor(num / 10);
}
return sum;
}
function isHappy(num) {
const seen = new Set();
while (num != 1 && !seen.has(num)) {
seen.add(num);
num = sumSquares(num);
}
return num == 1;
}
Im just wondering who can explain the algorithm of this solution step by step. I dont know how hashmap works. Can you also give a basic examples using a hashmap for me to understand this algorithm. Thank you!
var twoSum = function(nums, target) {
let hash = {};
for(let i = 0; i < nums.length; i++) {
const n = nums[i];
if(hash[target - n] !== undefined) {
return [hash[target - n], i];
}
hash[n] = i;
}
return [];
}
Your code takes an array of numbers and a target number/sum. It then returns the indexes in the array for two numbers which add up to the target number/sum.
Consider an array of numbers such as [1, 2, 3] and a target of 5. Your task is to find the two numbers in this array which add to 5. One way you can approach this problem is by looping over each number in your array and asking yourself "Is there a number (which I have already seen in my array) which I can add to the current number to get my target sum?".
Well, if we loop over the example array of [1, 2, 3] we first start at index 0 with the number 1. Currently, there are no numbers which we have already seen that we can add with 1 to get our target of 5 as we haven't looped over any numbers yet.
So, so far, we have met the number 1, which was at index 0. This is stored in the hashmap (ie object) as {'1': 0}. Where the key is the number and the value (0) is the index it was seen at. The purpose of the object is to store the numbers we have seen and the indexes they appear at.
Next, the loop continues to index 1, with the current number being 2. We can now ask ourselves the question: Is there a number which I have already seen in my array that I can add to my current number of 2 to get the target sum of 5. The amount needed to add to the current number to get to the target can be obtained by doing target-currentNumber. In this case, we are currently on 2, so we need to add 3 to get to our target sum of 5. Using the hashmap/object, we can check if we have already seen the number 3. To do this, we can try and access the object 3 key by doing obj[target-currentNumber]. Currently, our object only has the key of '1', so when we try and access the 3 key you'll get undefined. This means we haven't seen the number 3 yet, so, as of now, there isn't anything we can add to 2 to get our target sum.
So now our object/hashmap looks like {'1': 0, '2': 1}, as we have seen the number 1 which was at index 0, and we have seen the number 2 which was at index 1.
Finally, we reach the last number in your array which is at index 2. Index 2 of the array holds the number 3. Now again, we ask ourselves the question: Is there a number we have already seen which we can add to 3 (our current number) to get the target sum?. The number we need to add to 3 to get our target number of 5 is 2 (obtained by doing target-currentNumber). We can now check our object to see if we have already seen a number 2 in the array. To do so we can use obj[target-currentNumber] to get the value stored at the key 2, which stores the index of 1. This means that the number 2 does exist in the array, and so we can add it to 3 to reach our target. Since the value was in the object, we can now return our findings. That being the index of where the seen number occurred, and the index of the current number.
In general, the object is used to keep track of all the previously seen numbers in your array and keep a value of the index at which the number was seen at.
Here is an example of running your code. It returns [1, 2], as the numbers at indexes 1 and 2 can be added together to give the target sum of 5:
const twoSum = function(nums, target) {
const hash = {}; // Stores seen numbers: {seenNumber: indexItOccurred}
for (let i = 0; i < nums.length; i++) { // loop through all numbers
const n = nums[i]; // grab the current number `n`.
if (hash[target - n] !== undefined) { // check if the number we need to add to `n` to reach our target has been seen:
return [hash[target - n], i]; // grab the index of the seen number, and the index of the current number
}
hash[n] = i; // update our hash to include the. number we just saw along with its index.
}
return []; // If no numbers add up to equal the `target`, we can return an empty array
}
console.log(twoSum([1, 2, 3], 5)); // [1, 2]
A solution like this might seem over-engineered. You might be wondering why you can't just look at one number in the array, and then look at all the other numbers and see if you come across a number that adds up to equal the target. A solution like that would work perfectly fine, however, it's not very efficient. If you had N numbers in your array, in the worst case (where no two numbers add up to equal your target) you would need to loop through all of these N numbers - that means you would do N iterations. However, for each iteration where you look at a singular number, you would then need to look at each other number using a inner loop. This would mean that for each iteration of your outer loop you would do N iterations of your inner loop. This would result in you doing N*N or N2 work (O(N2) work). Unlike this approach, the solution described in the first half of this answer only needs to do N iterations over the entire array. Using the object, we can find whether or not a number is in the object in constant (O(1)) time, which means that the total work for the above algorithm is only O(N).
For further information about how objects work, you can read about bracket notation and other property accessor methods here.
You may want to check out this method, it worked so well for me and I have written a lot of comments on it to help even a beginner understand better.
let nums = [2, 7, 11, 15];
let target = 9;
function twoSums(arr, t){
let num1;
//create the variable for the first number
let num2;
//create the variable for the second number
let index1;
//create the variable for the index of the first number
let index2;
//create the variable for the index of the second number
for(let i = 0; i < arr.length; i++){
//make a for loop to loop through the array elements
num1 = arr[i];
//assign the array iteration, i, value to the num1 variable
//eg: num1 = arr[0] which is 2
num2 = t - num1;
//get the difference between the target and the number in num1.
//eg: t(9) - num1(2) = 7;
if(arr.includes(num2)){
//check to see if the num2 number, 7, is contained in the array;
index1 = arr.indexOf(num2);
//if yes get the index of the num2 value, 7, from the array,
// eg: the index of 7 in the array is 1;
index2 = arr.indexOf(num1)
//get the index of the num1 value, which is 2, theindex of 2 in the array is 0;
}
}
return(`[${index1}, ${index2}]`);
//return the indexes in block parenthesis. You may choose to create an array and push the values into it, but consider space complexities.
}
console.log(twoSums(nums, target));
//call the function. Remeber we already declared the values at the top already.
//In my opinion, this method is best, it considers both time complexity and space complexityat its lowest value.
//Time complexity: 0(n)
function twoSum(numbers, target) {
for (let i = 0; i < numbers.length; i++) {
for (let j = i + 1; j < numbers.length; j++) {
if (numbers[i] + numbers[j] === target) {
return [numbers.indexOf(numbers[i]), numbers.lastIndexOf(numbers[j])];
}
}
}
}
I've found shuffling algorithm seems work fine.
const questions = [
{ name: "Ananda or Nalanda" },
{ name: "Sunny or Rainy" },
{ name: "Facebook or Instagram" },
{ name: "IOS or Android" },
{ name: "Mc or KFC" }
];
questions.sort(() => Math.random() - 0.5)
questions.forEach(e=>{
console.log(e.name)
})
But I couldn't think how this work in the syntax. I know that Math.random() will generate a number between 0 and 1. Also sort is standard function to sort. But how do these two functions shuffle my array? Why does it deduct 0.5 from Math.random()?
The return value from the .sort callback is expected to be a positive number, 0, or a negative number. So, subtracting 0.5 from a variable with a range of [0, 1) results in a range of [-0.5, 0.5) - an equal distribution of randomly sorting a before b, and of sorting b before a (where a and b are the elements being compared). This kind of randomly sorts the array, by randomly determining whether an a comes before or after a b.
If you didn't subtract 0.5, or subtracted something other than 0.5, the results would be significantly biased.
BUT, this is not a good way to randomly sort an array; the results here will be somewhat biased as well:
// an array of 'a' to 'f'
const questions = Array.from(
{ length: 6 },
(_, i) => String.fromCharCode(i + 97)
);
const positionFrequency = {};
for (let i = 0; i < 1e5; i++) {
const sorted = questions.slice().sort(() => Math.random() - 0.5);
sorted.forEach((char, i) => {
if (!positionFrequency[char]) {
positionFrequency[char] = {};
}
positionFrequency[char][i] = (positionFrequency[char][i] || 0) + 1;
});
}
console.log(positionFrequency);
Please run the snippet - it is very biased! In Chrome, a occurs in the first position some 28% of the time, despite the fact that it should occur there only 1/6th (16.667%) of the time. In Firefox 56, it's even more biased than that.
This is because the sorting algorithm is not stable - the results depend on which elements are compared against which other elements first (which is implementation-dependent). You can read more details about how exactly this kind of random-sorting is biased here:
http://www.robweir.com/blog/2010/02/microsoft-random-browser-ballot.html
Array.sort sorts an array given a compare function. The sort function compares all the items in the array using the compare function to determine which ones should go before other ones. The compare function must return a negative, zero, or positive value. It uses this value to determine which value should go first.
For example, when comparing values a and b, the sort function will call compare_function(a, b) and if it returns a negative value, sort will place a before b in the final sorted array. If the compare function returns a positive value, sort will place a after b.
So in your example, Math.random() - 0.5 is the compare function. Because Math.random() normally returns a value between 0 and 1, Math.random() - 0.5 will return a random number between -0.5 and 0.5. Therefore, the chance that the compare function (which is Math.random() - 0.5) will return a positive number is the same as the chance that the compare function will return a negative value.
In other words, a random number between -0.5 and +0.5 is used to determine whether an arbitrary item a in your array goes before or after an item b. And because the chances of a positive versus negative number being used are the same, the chances of a before b versus b before a, in the sorted array, are the same.
I hope this answer is helpful!
Problem
I am trying to remove all of the odd numbers from an array. For example, if I pass an array like so...
var arr = [1,2,3,6,22,98,45,23,22,12]
...the function removes all of the odd numbers except for 23. Why doesn't it remove 23 as well? If different numbers are used or if the order of the numbers is changed, it is always the last odd number that is not removed. I don't understand why though, since the for loop should continue until it gets to the end of the array (i < passedArray.length).
I am sure it is something simple, but I can't figure it out! Any help would be much appreciated ;)
Code
// PROBLEM: Loop through arr removing all values that aren't even.
// The original array
var arr = [1, 2, 3, 6, 22, 98, 45, 23, 22, 12];
// Function to remove all odd numbers from the array that is passed to it.
// Returns the new array.
var getEvenNumbers = function(passedArray) {
for (var i = 0; i < passedArray.length; i++) {
// If the remainder of the current number in the array is equal to one, the number is odd so remove it from the array.
if ((passedArray[i] % 2) === 1) {
arr.splice(i, 1);
}
}
// Return the array with only even numbers left.
return passedArray;
};
// Call the function and store the results.
var evenNumbers = getEvenNumbers(arr);
// Alert the new array that only has even numbers.
alert(evenNumbers);
The bug is that once you've spliced a number out of the array, you still increment i. This makes the code skip the number that follows the one that you've just deleted.
Since the number that precedes the 23 is odd (45), you never look at the 23.
You are chaging your array with splice, so your length changes as well. You could change your function to this:
var getEvenNumbers = function(passedArray) {
var evenArr=[];
for (var i = 0; i < passedArray.length; i++) {
if ((passedArray[i] % 2) != 1) { // if its even, add it
evenArr.push(passedArray[i]);
}
}
// Return the array with only even numbers left.
return evenArr;
};