Javascript array sort speed affected by string length? - javascript

Just wondering, I have seen diverging opinions on this subject.
If you take an array of strings, say 1000 elements and use the sort method. Which one would be faster? An array in which the strings are 100 characters long or one in which the strings are only 3 characters long?
I tried to test but I have a bug with Firebug at the moment and Date() appears too random.
Thank you!

It depends what the strings contain, if they contain different characters, the rest of the string doesn't have to be checked for comparison so it doesn't matter.
For example, "abc" < "bca" Here only the first character had to be checked.
You can read the specs for this: http://ecma-international.org/ecma-262/5.1/#sec-11.8.5
Specifically:
Else, both px and py are Strings
If py is a prefix of px, return false. (A String value p is a prefix of String value
q if q can be the result of concatenating p and some other String r. Note that any
String is a prefix of itself, because r may be the empty String.)
If px is a prefix of py, return true.
Let k be the smallest nonnegative integer such that the character at position k within px is
different from the character at position k within py. (There must be such a k, for neither
String is a prefix of the other.)
Let m be the integer that is the code unit value for the character at position k within
px.
Let n be the integer that is the code unit value for the character at position k within
py.
If m < n, return true. Otherwise, return false.

It really depends on how different the strings are, but I guess the differences would be minimal due to the fact that what's called to do the comparison is way slower than actually comparing the strings.
But then again, modern browsers use some special optimizations for sort, so they cut some comparisons to speed things up. And this would happen more often sorting an array of short strings.
And FYI, if you want to make some benchmark, use a reliable tool like jsPerf.

Related

Space complexity of finding non-repeating character in string

Here is a simple algorithm exercise. The problem is to return the first non-repeating character. For example, I have this string: 'abbbcdd' and the answer is 'a' because 'a' appears before 'c'. In case it doesn't find any repeated characters, it will return '_'.
My solution works correctly, but my question is about the performance. The problem statement says: "Write a solution that only iterates over the string once and uses O(1) additional memory."
Here is my code:
console.log(solution('abbbcdd'))
function solution(str) {
let chars = buildCharMap(str)
for (let i in chars) {
if (chars[i] === 1) {
return i
}
}
return '_'
}
function buildCharMap(str) {
const charMap = {}
for (let i = 0; i < str.length; i++) {
!charMap[str[i]] ? charMap[str[i]] = 1 : charMap[str[i]]++
}
return charMap
}
Does my answer meet the requirement for space complexity?
The time complexity is straightforward: you have a loop over a string of length n, and another loop over an object with strictly at most n keys. The operations inside the loops take O(1) time, and the loops are consecutive (not nested), so the running time is O(n).
The space complexity is slightly more subtle. If the input were a list of numbers instead of a string, for example, then we could straightforwardly say that charMap takes O(n) space in the worst case, because all of the numbers in the list might be different. However, for problems on strings we have to be aware that there is a limited alphabet of characters which those strings could be formed of. If that alphabet has size a, then your charMap object can have at most a keys, so the space complexity is O(min(a, n)).
That alphabet is often explicit in the problem - for example, if the input is guaranteed to contain only lowercase letters, or only letters and digits. Otherwise, it may be implicit in the fact that strings are formed of Unicode characters (or in older languages, ASCII characters). In the former case, a = 26 or 62. In the latter case, a = 65,536 or 1,112,064 depending on if we're counting code units or code points, because Javascript strings are encoded as UTF-16. Either way, if a is a constant, then O(a) space is O(1) space - although it could be quite a large constant.
That means that in practice, your algorithm does use O(1) space. In theory, it uses O(1) space if the problem statement specifies a fixed alphabet, and O(min(a, n)) space otherwise; not O(n) space. Assuming the former, then your solution does meet the space-complexity requirement of the problem.
This raises the question of why, when analysing algorithms on lists of numbers, we don't likewise say that Javascript numbers have a finite "alphabet" defined by the IEEE 754 specification for floating point numbers. The answer is a bit philosophical; we analyse running time and auxiliary space using abstract models of computation which generally assume numbers, lists and other data structures don't have a fixed limit on their size. But even in those models, we assume strings are formed from some alphabet, and if the alphabet isn't fixed in the problem then we let the alphabet size be a variable a which we assume is independent of n. This is a sensible way to analyse algorithms on strings, because alphabet size and string length are independent in the problems we're usually interested in.

String comparison - Javascript

I'm trying to get my head around string comparisons in Javascript
function f(str){
return str[0] < str[str.length -1]
}
f("a+"); // false
In ASCII: 'a' == 97, '+' == 43
Am I correct in thinking my test: f(str) is based on ASCII values above?
You don't need a function or a complicated test pulling a string apart for this. Just do 'a' < '+' and learn from what happens. Or, more simply, check the char's charcode using 'a'.charCodeAt(0).
You are almost right. It is based on unicode code units (not code points, this is the 16-bit encoded version), not ascii on values.
From the ECMAScript 2015 specification:
If both px and py are Strings, then
If py is a prefix of px, return false. (A String value p is a prefix of String value q if q can be the result of concatenating p and some other String r. Note that any String is a prefix of itself, because r may be the empty String.)
If px is a prefix of py, return true.
Let k be the smallest nonnegative integer such that the code unit at index k within px is different from the code unit at index k within py. (There must be such a k, for neither String is a prefix of the other.)
Let m be the integer that is the code unit value at index k within px.
Let n be the integer that is the code unit value at index k within py.
If m < n, return true. Otherwise, return false.
Note2
The comparison of Strings uses a simple lexicographic ordering on
sequences of code unit values. There is no attempt to use the more
complex, semantically oriented definitions of character or string
equality and collating order defined in the Unicode specification.
Therefore String values that are canonically equal according to the
Unicode standard could test as unequal. In effect this algorithm
assumes that both Strings are already in normalized form. Also, note
that for strings containing supplementary characters, lexicographic
ordering on sequences of UTF-16 code unit values differs from that on
sequences of code point values.
Basically it means that string comparison is based on a lexicographical order of "code units", which is the numeric value of unicode characters.
JavaScript engines are allowed to use either UCS-2 or UTF-16 (which is the same for most practical purposes).
So, technically, your function is based on UTF-16 values and you were comparing 0x0061 and 0x002B.

Getting the numeric value after the hyphen in a string

How can I extract and get just the numeric value after the hyphen in a string?
Here is the input string:
var x = "-2147467259"
After some processing.... return:
alert(2147467259)
How do I accomplish this?
You could replace away the hyphen:
alert(+x.replace("-", ""));
And yes, the + is important. It converts a string to a number; so you're removing the hypen by replacing it with nothing, and then essentially casting the result of that operation into a number. This operation will also work if no hyphen is present.
You could also use substr to achieve this:
alert(+x.substr(1));
You could also use parseInt to convert the string to a number (which will end up negative if a hyphen is persent), and then find its absolute value:
alert(Math.abs(parseInt(x, 10));
As Bergi notes, if you can be sure that the first character in the string is always a hyphen, you can simple return its negative, which will by default cast the value into a number and then perform the negative operation on it:
alert(-x);
You could also check to see if the number is negative or positive via a tertiary operator and then perform the respective operation on it to ensure that it is a positive Number:
x = x >= 0 ? +x : -x;
This may be cheaper in terms of performance than using Math.abs, but the difference will be minuscule either way.
As you can see, there really are a variety of ways to achieve this. I'd recommend reading up on JavaScript string functions and number manipulation in general, as well as examining JavaScript's Math object to get a feel for what tools are available to you when you go to solve a problem.
How about:
Math.abs(parseInt("-2147467259"))
Or
"-2147467259".replace('-','')
or
"-2147467259".replace(/\-/,'')
#1 option is converting the string to numbers. The #2 approach is removing all - from the string and the #3 option even though it will not be necessary on this example uses Regular Expression but I wanted to show the possibility of using RegEx in replace situations.
If you need a number as the final value #1 is your choice if you need strings #2 is your choice.

How to find a "(a substring)" in a given "text" without using Regular expressions?

Recently I was asked in an interview, where the interviewer asked me this above question.
I was surely perplexed and answered him by using a for loop implementation where
we would find the length of the given "text" (using JavaScript) ... str.length() ...
we would take the first element of the "pattern" and find that in the "text".
If found we would increment the array .. As strings are stored as array in JavaScript ..
And we would find the "(a substring)" in similar way..
know this might be wrong way , but can anyone suggest a better way ? Thank you :-)
String.prototype.search (regexp)
When the search method is called with argument regexp, the following steps are taken:
Call CheckObjectCoercible passing the this value as its argument.
Let string be the result of calling ToString, giving it the this value as its argument.
If Type(regexp) is Object and the value of the [[Class]] internal property of regexp is "RegExp", then let rx be regexp;
Else, let rx be a new RegExp object created as if by the expression new RegExp(regexp) where RegExp is the standard built-in constructor with that name.
Search the value string from its beginning for an occurrence of the regular expression pattern rx. Let result be a Number indicating the offset within string where the pattern matched, or –1 if there was no match. The lastIndex and global properties of regexp are ignored when performing the search. The lastIndex property of regexp is left unchanged.
Return result.
Or if you want to avoid the word RegExp alltogether and search for a sub-string then
String.prototype.indexOf (searchString, position)
If searchString appears as a substring of the result of converting this object to a String, at one or more positions that are greater than or equal to position, then the index of the smallest such position is returned; otherwise, ‑1 is returned. If position is undefined, 0 is assumed, so as to search all of the String.
The indexOf method takes two arguments, searchString and position, and performs the following steps:
Call CheckObjectCoercible passing the this value as its argument.
Let S be the result of calling ToString, giving it the this value as its argument.
Let searchStr be ToString(searchString).
Let pos be ToInteger(position). (If position is undefined, this step produces the value 0).
Let len be the number of characters in S.
Let start be min(max(pos, 0), len).
Let searchLen be the number of characters in searchStr.
Return the smallest possible integer k not smaller than start such that k+ searchLen is not greater than len, and for all nonnegative integers j less than searchLen, the character at position k+j of S is the same as the character at position j of searchStr; but if there is no such integer k, then return the value -1.
I think the answer depends on the context, and the context seems to be lacking.
If the question was about algorithms, then I believe your best choice of algorithms (i.e., the fastest algorithm) is Boyer–Moore string search.
If the question was a HowTo in PHP, then its probably string.indexOf. And str.search would probably not be a valid answer since it takes a regex.
S[i] refers to the character at index i of string S, counting from 1.
S[i..j] refers to the substring of string S starting at index i and ending at j, inclusive.
A prefix of S is a substring S[1..i] for some i in range [1, n], where n is the length of S.
A suffix of S is a substring S[i..n] for some i in range [1, n], where n is the length of S.
The string to be searched for is called the pattern and is referred to with symbol P.
The string being searched in is called the text and is referred to with symbol T.
The length of P is n.
The length of T is m.
An alignment of P to T is an index k in T such that the last character of P is aligned with index k of T.
A match or occurrence of P occurs at an alignment if P is equivalent to T[(k-n+1)..k].

Working with string (array?) of bits of an unspecified length

I'm a javascript code monkey, so this is virgin territory for me.
I have two "strings" that are just zeros and ones:
var first = "00110101011101010010101110100101010101010101010";
var second = "11001010100010101101010001011010101010101010101";
I want to perform a bitwise & (which I've never before worked with) to determine if there's any index where 1 appears in both strings.
These could potentially be VERY long strings (in the thousands of characters). I thought about adding them together as numbers, then converting to strings and checking for a 2, but javascript can't hold precision in large intervals and I get back numbers as strings like "1.1111111118215729e+95", which doesn't really do me much good.
Can I take two strings of unspecified length (they may not be the same length either) and somehow use a bitwise & to compare them?
I've already built the loop-through-each-character solution, but 1001^0110 would strike me as a major performance upgrade. Please do not give the javascript looping solution as an answer, this question is about using bitwise operators.
As you already noticed yourself, javascript has limited capabilities if it's about integer values. You'll have to chop your strings into "edible" portions and work your way through them. Since the parseInt() function accepts a base, you could convert 64 characters to an 8 byte int (or 32 to a 4 byte int) and use an and-operator to test for set bits (if (a & b != 0))
var first = "00110101011101010010101110100101010101010101010010001001010001010100011111",
second = "10110101011101010010101110100101010101010101010010001001010001010100011100",
firstInt = parseInt(first, 2),
secondInt = parseInt(second, 2),
xorResult = firstInt ^ secondInt, //524288
xorString = xorResult.toString(2); //"10000000000000000000"

Categories

Resources