Recently doing leetcode but encounter difficulties in this 4 sum question. For the kSum function below, I saw some of the solutions online, passing an empty array as a parameter to store the result. I think it makes kSum() too many parameters.
I am thinking of refactoring kSum() holds a parameter of itself but not much process. It return something strange(eg. an empty array)
I would like to ask what I am missing to make my algorithm works? I think the problem may due to the second for loop which loop through kSum(nums, i+1, ...) ?
const fourSum = (nums, target) => {
const sortedNumsArray = nums.sort((a, b) => a - b)
return kSum(sortedNumsArray, 0, 4, target)
}
const kSum = (nums, start, k, target) => {
const result = [];
if( nums.length === start || nums[nums.length - 1] * k < target || nums[start] * k > target) return result;
if (k === 2) {
return twoSum(nums, 0, target)
} else {
let shouldCheck = false;
for (let i = start; i < nums.length; i++) {
if (shouldCheck && nums[i] !== nums[i - 1]) {
for (let set of kSum(nums, i + 1, k - 1, target - nums[i])) {
result.push([nums[i]])
result[result.length - 1].concat(set)
}
}
shouldCheck = true;
}
}
return result;
}
const twoSum = (nums, start, target) => {
let left = start;
let right = nums.length - 1
let subResult = []
while (left < right) {
let sum = nums[left] + nums[right]
if (sum === target) {
subResult.push([nums[left++], nums[right--]])
while (left < right && nums[left] === nums[left + 1]) { left++ }
while (left < right && nums[right] === nums[right - 1]) { right-- }
} else if (sum > target) {
right--
} else {
left++
}
}
return subResult;
}
I am trying to solve the fibonacci in recrusive way and I think i got a bug in my code.I can't figurer out where it is.
Example:
fib(4) === 3
function fib(n, array = [0, 1], count = 0) {
if (n == 0) {
return 0;
}
if (n == 1) {
return 1;
}
array.push(array[count] + array[count + 1]);
console.log(array)
if (n === array.length-1) {
return array.pop()
}
fib(n, array, count + 1);
}
let ans=fib(2)
console.log(ans)
you can do by this way using recursion
var i = 0, a = 0, b = 1, c = 0;
var out = "";
function fibonacci(n){
i = 0;
if(i < n){
out += a + ",";
c = a + b;
a = b;
b = c;
i++;
console.log(out);
fibonacci(n - i);
}
}
fibonacci(10);
the task is to create a recursion, displaying Fibonacci numbers. I need to display the number chain of Fibonacci numbers in the console, without (for) loop.
I have optimised the recursion and displayed the numbers with a (for) loop.
"use strict";
var arr = []
let skkak = function(n)
{
if (n <= 1)
{
return n;
}
if(!isNaN(arr[n])){
return arr[n];
}
else
{
let result = skkak(n - 1) + skkak(n - 2)
arr[n] = result;
return result;
}
}
for(let i=12; i > 0; i--)
{
console.log(skkak(i));
}
no errors
This version is using while (not recursive)
"use strict";
var arr = []
let skkak = function(n)
{
if (n <= 1)
{
return n;
}
if(!isNaN(arr[n])){
return arr[n];
}
else
{
let result = skkak(n - 1) + skkak(n - 2)
arr[n] = result;
return result;
}
}
let i = 12;
while(i > 0)
{
console.log(skkak(i));
i--;
}
Recursive approach
fibonacci = (n) =>
{
if (n===1)
{
return [0, 1];
}
else
{
let s = fibonacci(n - 1);
s.push(s[s.length - 1] + s[s.length - 2]);
return s;
}
};
console.log(fibonacci(5)); // [0,1,1,2,3,5]
I'm new to coding and have been given this question that I cannot seem to get right:
Create a function that takes an array of positive integers and returns an array of the factorials of these numbers.
E.g. [4, 3, 2] => [24, 6, 2]
The factorial of a number is the product of that number and all the integers below it.
E.g. the factorial of 4 is 4 * 3 * 2 * 1 = 24
If the number is less than 0, reject it.
The code that I have created is this;
function getFactorials(nums) {
if (nums === 0 || nums === 1)
return 1;
for (var i = nums - 1; i >= 1; i--) {
nums *= i;
}
return nums;
}
The code is being run against this test;
describe("getFactorials", () => {
it("returns [] when passed []", () => {
expect(getFactorials([])).to.eql([]);
});
it("returns one factorial", () => {
expect(getFactorials([3])).to.eql([6]);
});
it("returns multiple factorials", () => {
expect(getFactorials([3, 4, 5])).to.eql([6, 24, 120]);
});
it("returns largest factorials", () => {
expect(getFactorials([3, 8, 9, 10])).to.eql([6, 40320, 362880, 3628800]);
});
});
How should I do this?
First off, make a recursive function that calculates the factorial of a single number:
function factorial(num) {
if (num == 0 || num == 1) {
return 1;
}
return num * factorial(num - 1);
}
Then to do it for an array, just use Array.prototype.map() like so:
function getFactorials(arr) {
var result = arr.map(x => factorial(x));
return result;
}
Here's a demonstration:
function factorial(num) {
if (num == 0 || num == 1) {
return 1;
}
return num * factorial(num - 1);
}
function getFactorials(arr) {
var result = arr.map(x => factorial(x));
return result;
}
console.log(getFactorials([4, 8, 10]));
console.log(getFactorials([]));
console.log(getFactorials([1, 2, 3, 4, 5]));
Hopefully this helps!
You need to separate function into two functions, one for iterating the array and collecting the calculated values and the other to get the facorial of a number.
function getFactorials(nums) {
var result = [],
i;
for (i = 0; i < nums.length; i++) {
result.push(getFactorial(nums[i]));
}
return result;
}
function getFactorial(n) {
if (n === 0 || n === 1) return 1;
return n * getFactorial(n - 1);
}
console.log(getFactorials([]));
console.log(getFactorials([3]));
console.log(getFactorials([3, 4, 5]));
console.log(getFactorials([3, 8, 9, 10]));
This method will take an array of numbers and will return an array of factorial numbers of them,
function getFactorials(array) {
var facArray = [];
for (var j = 0; j < array.length; j++) {
num = array[j];
if (num === 0 || num === 1)
return 1;
for (var i = num - 1; i >= 1; i--) {
num *= i;
}
facArray.push(num);
}
return facArray;
}
console.log(getFactorials([4, 3, 2]));
function getFactorials(nums) {
return numbers = Array.from(nums).map(function factorializeSingleNumber(num) {
if (num == 0 || num == 1) return 1
else return num * factorializeSingleNumber(num - 1)
})
}
The best way I find of tackling these is to break the problem down. So in this case, work a solution that factorializes a single number. When that is working you can add this 'working code' into a map or loop, to work through the array.
My above solution uses recursion but could be a simple 'for loop' too
it's a simple code, but returns different results in Andriod and Iphone.
var str = [1,2,3,4,5].sort(function () {
return -1;
})
document.write(str);
In MDN(https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort) it says
If compareFunction(a, b) is less than 0, sort a to a lower index than b, i.e. a comes first.
If compareFunction(a, b) returns 0, leave a and b unchanged with respect to each other, but sorted with respect to all different elements. Note: the ECMAscript standard does not guarantee this behaviour, and thus not all browsers (e.g. Mozilla versions dating back to at least 2003) respect this.
If compareFunction(a, b) is greater than 0, sort b to a lower index than a.
compareFunction(a, b) must always return the same value when given a specific pair of elements a and b as its two arguments. If inconsistent results are returned then the sort order is undefined.
So the result should be 1,2,3,4,5.
But is Iphone it shows 5,4,3,2,1
Here is a link for you to try this code. http://www.madcoder.cn/demos/ios-test.html
And after I did more and more test. I found Iphone is doing a different sorting.
Here is a link shows how sort works: http://www.madcoder.cn/demos/ios-test2.html
The javascript engines use different algorithms for their sort function. Since the compare function doesn't compare values, you get the result of the inner workings of the different algorithms instead of having a sorted result.
Looking at the source code of V8 engine (Chrome) and JavaScriptCore (which seems to be used by Safari, or at least the sort function gives the same result, so I guess it uses the same kind of algorithm), you can view the functions that are being used.
Not that it might not be exactly the functions used, what's important is that the algorithms are different. They give the same result if you actually compare values, but if not, the result is dependent on the way they operate, not on the function itself. At least not completely.
Here's V8 engine sorting function. You'll see that for arrays bigger than 10 elements, the algorithm isn't the same, so the result for arrays smaller than 10 elements is different than for those bigger than 10 elements.
You can find following algorithms here: https://code.google.com/p/chromium/codesearch#chromium/src/v8/src/js/array.js&q=array&sq=package:chromium&dr=C
comparefn = function(a, b) {
return -1
}
var InsertionSort = function InsertionSort(a, from, to) {
for (var i = from + 1; i < to; i++) {
var element = a[i];
for (var j = i - 1; j >= from; j--) {
var tmp = a[j];
var order = comparefn(tmp, element);
if (order > 0) {
a[j + 1] = tmp;
} else {
break;
}
}
a[j + 1] = element;
}
console.log(a);
}
var GetThirdIndex = function(a, from, to) {
var t_array = new InternalArray();
// Use both 'from' and 'to' to determine the pivot candidates.
var increment = 200 + ((to - from) & 15);
var j = 0;
from += 1;
to -= 1;
for (var i = from; i < to; i += increment) {
t_array[j] = [i, a[i]];
j++;
}
t_array.sort(function(a, b) {
return comparefn(a[1], b[1]);
});
var third_index = t_array[t_array.length >> 1][0];
return third_index;
}
var QuickSort = function QuickSort(a, from, to) {
var third_index = 0;
while (true) {
// Insertion sort is faster for short arrays.
if (to - from <= 10) {
InsertionSort(a, from, to);
return;
}
if (to - from > 1000) {
third_index = GetThirdIndex(a, from, to);
} else {
third_index = from + ((to - from) >> 1);
}
// Find a pivot as the median of first, last and middle element.
var v0 = a[from];
var v1 = a[to - 1];
var v2 = a[third_index];
var c01 = comparefn(v0, v1);
if (c01 > 0) {
// v1 < v0, so swap them.
var tmp = v0;
v0 = v1;
v1 = tmp;
} // v0 <= v1.
var c02 = comparefn(v0, v2);
if (c02 >= 0) {
// v2 <= v0 <= v1.
var tmp = v0;
v0 = v2;
v2 = v1;
v1 = tmp;
} else {
// v0 <= v1 && v0 < v2
var c12 = comparefn(v1, v2);
if (c12 > 0) {
// v0 <= v2 < v1
var tmp = v1;
v1 = v2;
v2 = tmp;
}
}
// v0 <= v1 <= v2
a[from] = v0;
a[to - 1] = v2;
var pivot = v1;
var low_end = from + 1; // Upper bound of elements lower than pivot.
var high_start = to - 1; // Lower bound of elements greater than pivot.
a[third_index] = a[low_end];
a[low_end] = pivot;
// From low_end to i are elements equal to pivot.
// From i to high_start are elements that haven't been compared yet.
partition: for (var i = low_end + 1; i < high_start; i++) {
var element = a[i];
var order = comparefn(element, pivot);
if (order < 0) {
a[i] = a[low_end];
a[low_end] = element;
low_end++;
} else if (order > 0) {
do {
high_start--;
if (high_start == i) break partition;
var top_elem = a[high_start];
order = comparefn(top_elem, pivot);
} while (order > 0);
a[i] = a[high_start];
a[high_start] = element;
if (order < 0) {
element = a[i];
a[i] = a[low_end];
a[low_end] = element;
low_end++;
}
}
}
if (to - high_start < low_end - from) {
QuickSort(a, high_start, to);
to = low_end;
} else {
QuickSort(a, from, low_end);
from = high_start;
}
}
};
InsertionSort([1, 2, 3, 4, 5], 0, 5);
//QuickSort is recursive and calls Insertion sort, so you'll have multiple logs for this one
QuickSort([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13], 0, 13);
//You'll see that for arrays bigger than 10, QuickSort is called.
var srt = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13].sort(function() {
return -1
})
console.log(srt)
And JavaScriptCore uses merge sort. You can find this algorithm here:
http://trac.webkit.org/browser/trunk/Source/JavaScriptCore/builtins/ArrayPrototype.js
function min(a, b) {
return a < b ? a : b;
}
function merge(dst, src, srcIndex, srcEnd, width, comparator) {
var left = srcIndex;
var leftEnd = min(left + width, srcEnd);
var right = leftEnd;
var rightEnd = min(right + width, srcEnd);
for (var dstIndex = left; dstIndex < rightEnd; ++dstIndex) {
if (right < rightEnd) {
if (left >= leftEnd || comparator(src[right], src[left]) < 0) {
dst[dstIndex] = src[right++];
continue;
}
}
dst[dstIndex] = src[left++];
}
}
function mergeSort(array, valueCount, comparator) {
var buffer = [];
buffer.length = valueCount;
var dst = buffer;
var src = array;
for (var width = 1; width < valueCount; width *= 2) {
for (var srcIndex = 0; srcIndex < valueCount; srcIndex += 2 * width)
merge(dst, src, srcIndex, valueCount, width, comparator);
var tmp = src;
src = dst;
dst = tmp;
}
if (src != array) {
for (var i = 0; i < valueCount; i++)
array[i] = src[i];
}
return array;
}
console.log(mergeSort([1, 2, 3, 4, 5], 5, function() {
return -1;
}))
Again these may not be exactly the functions used in each browser, but it shows you how different algorithms will behave if you don't actually compare values.