How can I calculate similarity between two strings in C#? - c#

I'm looking to assess similarity (including case) between two strings and give a value between 0 and 1.
I tried the Levenshtein distance implementation but it only gives integers and does not compare inner alphabets.
For e.g. comparing "ABCD" and "Abcd" gives distance of 3 and "AOOO" also gives a distance of 3 but clearly "Abcd" is better match than "AOOO".
So compared to "ABCD" I want "ABcd" to be most similar then "Abcd" then "AOOO" then "AOOOO"
I've also looked here but I am not looking for a variable length algorithm.
Thanks

Try something like this
double d = (LevenshteinDist(s, t) + LevenshteinDist(s.ToLower(), t.ToLower())) /
2.0 * Math.Max(s.Length, t.Length);
If you want to give less importance to case differences than letter differences, you can give different weights to the terms
double d = (0.15*LevenshteinDist(s, t) +
0.35*LevenshteinDist(s.ToLower(), t.ToLower())) /
Math.Max(s.Length, t.Length);
Note that the weights sum up to 0.5, thus makting the division by 2.0 obsolete.

Adapt Levenshtein Distance with a custom table T. Let the cost of insertion = 1. The cost of deletion also 1. Let T(c,d) denote the penalty of replacing c with d. T(c,c) should be = 0. T(c,d) should be <= 2.
Define Max(n,m) be the maximum theoretical distance of strings of length n and m. Obviously, Max(n,m) = n+m.
Define Distance(s,t) be the cost of changing s to t divided by Max(s,t). There you go.
Be careful in defining T so that the definition obeys distance axioms:
Distance(s,s) = 0
Distance(s,t) = Distance(t,s)
Distance(s,t) <= Distance(s,u) + Distance(u,t)
Then it will be more useful in more situations.

bool check(string[] a, string s)
{
for (int i = 0; i < a.Length; i++)
if (s == a[i])
return true;
return false;
}
public double simi(string string1, string string2)
{
int sub1 = 0;
int sub2 = 0;
string[] sp1 = new string[string1.Length - 1];
string[] sp2 = new string[string2.Length - 1];
string[] sp3 = new string[string1.Length - 1];
string[] sp4 = new string[string2.Length - 1];
for (int i = 0; i < string1.Length - 1; i++)
{
string x = "";
x = string1.Substring(i, 2);
sp1[sub1] = x;
++sub1;
}
for (int i = 0; i < string2.Length - 1; i++)
{
string x = "";
x = string2.Substring(i, 2);
sp2[sub2] = x;
++sub2;
}
int j = 0, k = 0;
for (int i = 0; i < sp1.Length; i++)
if (check(sp3, sp1[i]) == true)
{
continue;
}
else
{
sp3[j] = sp1[i];
j++;
}
for (int i = 0; i < sp2.Length; i++)
if (check(sp4, sp2[i]) == true)
{
continue;
}
else
{
sp4[k] = sp2[i];
k++;
}
Array.Resize(ref sp3, j);
Array.Resize(ref sp4, k);
Array.Sort<string>(sp3);
Array.Sort<string>(sp4);
int n = 0;
for (int i = 0; i < sp3.Length; i++)
{
if (check(sp4, sp3[i]))
{
n++;
}
}
double resulte;
int l1 = sp3.Length;
int l2 = sp4.Length;
resulte = ((2.0 * Convert.ToDouble(n)) / Convert.ToDouble(l1 + l2)) * 100;
return resulte;
}

Related

Filter records by string using wildcard in any position

I'd like to filter records with lambda expression. The condition is if it contains a given string, or nearly the same string with one character difference.
Nearly the same means: one of the characters can be any character, but only one.
For example:
The search string: 'ABC' then the condition must be: '[any char]BC' or 'A[any char]C' or 'AB[any char]'
Does anyone know any professional solution?
Thanks in advance.
SOLUTION (thanks for LiamK):
var count = s1.Zip(s2, (c1, c2) => c1 == c2 ? 0 : 1).Sum();
The metric you are looking for is referred to as the Levenshtein distance between two strings. You can create an implementation of this algorithm, then utilize it inside of your where clause:
public IEnumerable<string> MyFunc(string searchString)
{
return myThingToSearch.Where(x => LevenshteinDistance(x, searchString) <= 1);
}
public static int LevenshteinDistance(string s1, string s2)
{
if (s1 == s2)
{
return 0;
}
if (s1.Length == 0)
{
return s2.Length;
}
if (s2.Length == 0)
{
return s1.Length;
}
int[] v0 = new int[s2.Length + 1];
int[] v1 = new int[s2.Length + 1];
for (int i = 0; i < v0.Length; i++)
{
v0[i] = i;
}
for (int i = 0; i < s1.Length; i++)
{
v1[0] = i + 1;
for (int j = 0; j < s2.Length; j++)
{
var cost = (s1[i] == s2[j]) ? 0 : 1;
v1[j + 1] = Math.Min(v1[j] + 1, Math.Min(v0[j + 1] + 1, v0[j] + cost));
}
for (int j = 0; j < v0.Length; j++)
{
v0[j] = v1[j];
}
}
return v1[s2.Length];
}
Side note: The Levenshtein distance metric will also match strings like 'BC' or 'ABCD' to the search string 'ABC' since those strings are technically only 'off-by-one' from the search string. I'm not sure if this is acceptable within your spec or not. If not, then let us know. That problem is a subset of approximate string matching and you would use the Hamming distance instead

Converting string[] to double[]

I have a text file that is being read in and then stored in a string[] which I then then convert into an int[], my bubblesort then should sort it but it doesn't because the values from the text files are decimals. So my question is how do I convert either the string[] or int[] to something that can accept decimal values, such as a double[] if there is such a thing. Thanks.
Code:
string[] sh1OpenData = File.ReadAllLines("SH1_Open.txt");
...
else if(input2.ToLower() == "open") //----
{
int[] intSh1OpenData = new int[sh1OpenData.Length];
for (int x = 0; x < sh1OpenData.Length; x++)
{
intSh1OpenData[x] = Convert.ToInt32(sh1OpenData[x]);
}
Console.WriteLine("\n");
Console.WriteLine("Unsorted");
for (int i = 0; i < intSh1OpenData.Length; i++)
{
Console.Write(intSh1OpenData[i] + " ");
Console.WriteLine(" ");
}
int temp = 0;
for (int write = 0; write < intSh1OpenData.Length; write++)
{
for (int sort = 0; sort < intSh1OpenData.Length - 1; sort++)
{
if (intSh1OpenData[sort] > intSh1OpenData[sort + 1])
{
temp = intSh1OpenData[sort + 1];
intSh1OpenData[sort + 1] = intSh1OpenData[sort];
intSh1OpenData[sort] = temp;
}
}
}
Console.WriteLine("\n\n\nSORTED");
for (int i = 0; i < intSh1OpenData.Length; i++)
Console.Write(intSh1OpenData[i] + "\n");
}
You should not be using int to do comparisons on string. Use String.Compare(return 0 if equal, -1 if less than, or 1 if greater than) or List.Sort() to sort string array
Pretty simple with LINQ
var asDouble = sh1OpenData.Select(x => Double.Parse(x)).OrderBy(x => x).ToArray();
This will give you a sorted (ascending order) array of Double.
Note: this assumes that all of sh1OpenData can be parsed as a Double, and will throw an exception if not.
The only changes that you will need to make are listed below:
double[] intSh1OpenData = new double[sh1OpenData.Length]; // double[] instead of int[]
for (int x = 0; x < sh1OpenData.Length; x++)
{
intSh1OpenData[x] = Convert.ToDouble(sh1OpenData[x]); // Convert to Double
}
also change the declaration of your temp variable to double temp;
Something that you could read through since you mentioned that you are new to programming:
C# Sort Arrays and Lists Examples
MSDN: List.Sort Method

sort list of points by distance in .NET

I need to sort a list of points by distance.
So for e.g.
input : [[1,2],[5,10],[2,4]...]
output : [[1,2],[2,4],[5,10]...]
(assuming that geometrically [1,2] and [2,4] are nearest & [2,4] & [5,10] are nearest.
I need them to sort it so they are ordered by distance i.e. on the geometrical graph, point a is nearest to point b , point b is nearest to c and so on.
Any idea?
Edit: Code example
public class Point
{
public double X {get;set;}
public double Y {get;set;}
}
List<Point> points = new List<Point>();
let say my points list is getting populated in random order (not by geometrical distance).
So points would look something like...
point ~ [[1,2],[5,10],[2,4]...]
Now my charting control just take the first & second point and draw a line between them. Which means it does not care which geometrical order is it in.
If I simply supply the "points" list as above its going to draw lines between each points and from charting point of view it would not look correct as they would be "zig-zag".
To make sure the charting control draws a straight line (& and not zig-zag) I have to pass the points in the right order which would look something like ...
destination points ~ [[1,2],[2,4],[5,10]...]
So my question is how to achieve this.
Note: Changing chart control is not an option here.
Thanks
The code first takes the nearest point to (0, 0) at the '0' index then start sorting the points by distance from the last spotted point..
C#:
List<Point> SortByDistance(List<Point> lst)
{
List<Point> output = new List<Point>();
output.Add(lst[NearestPoint(new Point(0, 0), lst)]);
lst.Remove(output[0]);
int x = 0;
for (int i = 0; i < lst.Count + x; i++)
{
output.Add(lst[NearestPoint(output[output.Count - 1], lst)]);
lst.Remove(output[output.Count - 1]);
x++;
}
return output;
}
int NearestPoint(Point srcPt, List<Point> lookIn)
{
KeyValuePair<double, int> smallestDistance = new KeyValuePair<double, int>();
for (int i = 0; i < lookIn.Count; i++)
{
double distance = Math.Sqrt(Math.Pow(srcPt.X - lookIn[i].X, 2) + Math.Pow(srcPt.Y - lookIn[i].Y, 2));
if (i == 0)
{
smallestDistance = new KeyValuePair<double, int>(distance, i);
}
else
{
if (distance < smallestDistance.Key)
{
smallestDistance = new KeyValuePair<double, int>(distance, i);
}
}
}
return smallestDistance.Value;
}
VB.Net:
Function SortByDistance(ByVal lst As List(Of Point)) As List(Of Point)
Dim out As New List(Of Point)
out.Add(lst(NearestPoint(New Point(0, 0), lst)))
lst.Remove(out(0))
Dim x As Integer = 0
For i As Integer = 0 To lst.Count - 1 + x
out.Add(lst(NearestPoint(out(out.Count - 1), lst)))
lst.Remove(out(out.Count - 1))
x += 1
Next
Return out
End Function
Function NearestPoint(ByVal srcPt As Point, ByVal lookIn As List(Of Point)) As Integer
Dim smallestDistance As KeyValuePair(Of Double, Integer)
For i As Integer = 0 To lookIn.Count - 1
Dim distance As Double = Math.Sqrt(Math.Pow(srcPt.X - lookIn(i).X, 2) + Math.Pow(srcPt.Y - lookIn(i).Y, 2))
If i = 0 Then
smallestDistance = New KeyValuePair(Of Double, Integer)(distance, i)
Else
If distance < smallestDistance.Key Then
smallestDistance = New KeyValuePair(Of Double, Integer)(distance, i)
End If
End If
Next
Return smallestDistance.Value
End Function
I think you want this, Dijkstra's algorithm. There is a c# project here.
What follows is unmodified code from that link
class Dijkstra
{
private int rank = 0;
private int[,] L;
private int[] C;
public int[] D;
private int trank = 0;
public Dijkstra(int paramRank,int [,]paramArray)
{
L = new int[paramRank, paramRank];
C = new int[paramRank];
D = new int[paramRank];
rank = paramRank;
for (int i = 0; i < rank; i++)
{
for (int j = 0; j < rank; j++) {
L[i, j] = paramArray[i, j];
}
}
for (int i = 0; i < rank; i++)
{
C[i] = i;
}
C[0] = -1;
for (int i = 1; i < rank; i++)
D[i] = L[0, i];
}
public void DijkstraSolving()
{
int minValue = Int32.MaxValue;
int minNode = 0;
for (int i = 0; i < rank; i++)
{
if (C[i] == -1)
continue;
if (D[i] > 0 && D[i] < minValue)
{
minValue = D[i];
minNode = i;
}
}
C[minNode] = -1;
for (int i = 0; i < rank; i++)
{
if (L[minNode, i] < 0)
continue;
if (D[i] < 0) {
D[i] = minValue + L[minNode, i];
continue;
}
if ((D[minNode] + L[minNode, i]) < D[i])
D[i] = minValue+ L[minNode, i];
}
}
public void Run()
{
for (trank = 1; trank >rank; trank++)
{
DijkstraSolving();
Console.WriteLine("iteration" + trank);
for (int i = 0; i < rank; i++)
Console.Write(D[i] + " ");
Console.WriteLine("");
for (int i = 0; i < rank; i++)
Console.Write(C[i] + " ");
Console.WriteLine("");
}
}
}
In a graph, a set of points (x1,y1), (x2,y2), (x3,y3)...(xn,yn) should be ordered on the value of any one co ordinate because it is not the nearest point that should come next in order, but the one with nearest x or y (whichever axis is taken as reference) co-ordinate value. So, the array to pass for charting should be:
var orderedPoints=points.OrderBy(p=>p.X);
In the above image, the length of the line L1 is greater than L2. But the point P2 and not P3 should be come after P1 since P2.X<P3.X

Latest Codility Time Problems

Just got done with the latest Codility, passed it, but didnt get 100% on it
Here is the spec
A prefix of a string S is any leading contiguous part of S. For example, "c" and "cod" are prefixes of the string "codility". For simplicity, we require prefixes to be non-empty.
The product of prefix P of string S is the number of occurrences of P multiplied by the length of P. More precisely, if prefix P consists of K characters and P occurs exactly T times in S, then the product equals K * T.
For example, S = "abababa" has the following prefixes:
"a", whose product equals 1 * 4 = 4,
"ab", whose product equals 2 * 3 = 6,
"aba", whose product equals 3 * 3 = 9,
"abab", whose product equals 4 * 2 = 8,
"ababa", whose product equals 5 * 2 = 10,
"ababab", whose product equals 6 * 1 = 6,
"abababa", whose product equals 7 * 1 = 7.
The longest prefix is identical to the original string. The goal is to choose such a prefix as maximizes the value of the product. In above example the maximal product is 10.
In this problem we consider only strings that consist of lower-case English letters (a−z).
So basically, it is a string traverse problem. I was able to pass all the validation parts, but I lost on the time. Here is what I wrote
int Solution(string S)
{
int finalCount = 0;
for (int i = 0; i <= S.Length - 1; i++)
{
string prefix = S.Substring(0, i + 1);
int count = 0;
for (int j = 0; j <= S.Length - 1; j++)
{
if (prefix.Length + j <= S.Length)
{
string newStr = S.Substring(j, prefix.Length);
if (newStr == prefix)
{
count++;
}
}
if (j == S.Length - 1)
{
int product = count * prefix.Length;
if (product > finalCount)
{
finalCount = product;
}
}
}
}
return finalCount;
}
I know that the nested loop is killing me, but I cannot think of a way to traverse the "sections" of the string without adding the other loop.
Any help would be appreciated.
Naive brute-force solution takes O(N ** 3) time. Choose length from 1 to N, get a prefix of its length and count occurences by brute-force searching. Сhoosing length takes O(N) time and brute force takes O(N ** 2) time, totally O(N ** 3).
If you use KMP or Z-algo, you can find occurences in O(N) time, so the whole solution will be O(N ** 2) time.
And you can precalc occurences, so it will take O(N) + O(N) = O(N) time solution.
vector<int> z_function(string &S); //z-function, z[0] = S.length()
vector<int> z = z_function(S);
//cnt[i] - count of i-length prefix occurrences of S
for (int i = 0; i < n; ++i)
++cnt[z[i]];
//if cnt[i] is in S, cnt[i - 1] will be in S
int previous = 0;
for (int i = n; i > 0; --i) {
cnt[i] += previous;
previous = cnt[i];
}
Here's the blog post, explaining all O(N ** 3), O(N ** 2), O(N) solutions.
my effort was as follows trying to eliminate unnecessary string compares, i read isaacs blog but it is in c how would this translate to c#, i even went as far as using arrays everywhere to avoid the string immutability factor but there was no improvement
int Rtn = 0;
int len = S.Length;
if (len > 1000000000)
return 1000000000;
for (int i = 1; i <= len; i++)
{
string tofind = S.Substring(0, i);
int tofindlen = tofind.Length;
int occurencies = 0;
for (int ii = 0; ii < len; ii++)
{
int found = FastIndexOf(S, tofind.ToCharArray(), ii);
if (found != -1)
{
if ((found == 0 && tofindlen != 1) || (found >= 0))
{
ii = found;
}
++occurencies ;
}
}
if (occurencies > 0)
{
int total = occurencies * tofindlen;
if (total > Rtn)
{
Rtn = total;
}
}
}
return Rtn;
}
static int FastIndexOf(string source, char[] pattern, int start)
{
if (pattern.Length == 0) return 0;
if (pattern.Length == 1) return source.IndexOf(pattern[0], start);
bool found;
int limit = source.Length - pattern.Length + 1 - start;
if (limit < 1) return -1;
char c0 = pattern[0];
char c1 = pattern[1];
// Find the first occurrence of the first character
int first = source.IndexOf(c0, start, limit);
while ((first != -1) && (first + pattern.Length <= source.Length))
{
if (source[first + 1] != c1)
{
first = source.IndexOf(c0, ++first);
continue;
}
found = true;
for (int j = 2; j < pattern.Length; j++)
if (source[first + j] != pattern[j])
{
found = false;
break;
}
if (found) return first;
first = source.IndexOf(c0, ++first);
}
return -1;
}
I only got a 43... I like my code though! Same script in javascript got 56 for what it's worth.
using System;
class Solution
{
public int solution(string S)
{
int highestCount = 0;
for (var i = S.Length; i > 0; i--)
{
int occurs = 0;
string prefix = S.Substring(0, i);
int tempIndex = S.IndexOf(prefix) + 1;
string tempString = S;
while (tempIndex > 0)
{
tempString = tempString.Substring(tempIndex);
tempIndex = tempString.IndexOf(prefix);
tempIndex++;
occurs++;
}
int product = occurs * prefix.Length;
if ((product) > highestCount)
{
if (highestCount > 1000000000)
return 1000000000;
highestCount = product;
}
}
return highestCount;
}
}
This works better
private int MaxiumValueOfProduct(string input)
{
var positions = new List<int>();
int max = 0;
for (int i = 1; i <= input.Length; i++)
{
var subString = input.Substring(0, i);
int position = 0;
while ((position < input.Length) &&
(position = input.IndexOf(subString, position, StringComparison.OrdinalIgnoreCase)) != -1)
{
positions.Add(position);
++position;
}
var currentMax = subString.Length * positions.Count;
if (currentMax > max) max = currentMax;
positions.Clear();
}
return max;
}

How to find the Largest Difference in an Array

Suppose I have an array of integers:
int[] A = { 10, 3, 6, 8, 9, 4, 3 };
My goal is to find the largest difference between A[Q] and A[P] such that Q > P.
For example, if P = 2 and Q = 3, then
diff = A[Q] - A[P]
diff = 8 - 6
diff = 2
If P = 1 and Q = 4
diff = A[Q] - A[P]
diff = 9 - 3
diff = 6
Since 6 is the largest number between all the difference, that is the answer.
My solution is as follows (in C#) but it is inefficient.
public int solution(int[] A) {
int N = A.Length;
if (N < 1) return 0;
int difference;
int largest = 0;
for (int p = 0; p < N; p++)
{
for (int q = p + 1; q < N; q++)
{
difference = A[q] - A[p];
if (difference > largest)
{
largest = difference;
}
}
}
return largest;
}
How can I improve this so it will run at O(N)? Thanks!
Simply getting the max and min wont work. Minuend (Q) should come after the Subtrahend (P).
This question is based on the "Max-profit" problem in codility (http://codility.com/train/). My solution only scored 66%. It requires O(N) for a score of 100%.
The following code runs in O(n) and should conform to the specification (preliminary tests on codility were successful):
public int solution(int[] A)
{
int N = A.Length;
if (N < 1) return 0;
int max = 0;
int result = 0;
for(int i = N-1; i >= 0; --i)
{
if(A[i] > max)
max = A[i];
var tmpResult = max - A[i];
if(tmpResult > result)
result = tmpResult;
}
return result;
}
Update:
I submitted it as solution and it scores 100%.
Update 02/26/16:
The original task description on codility stated that "each element of array A is an integer within the range [0..1,000,000,000]."
If negative values would have been allowed as well, the code above wouldn't return the correct value. This could be fixed easily by changing the declaration of max to int max = int.MinValue;
Here is the O(n) Java implementation
public static int largestDifference(int[] data) {
int minElement=data[0], maxDifference=0;
for (int i = 1; i < data.length; i++) {
minElement = Math.min(minElement, data[i]);
maxDifference = Math.max(maxDifference, data[i] - minElement);
}
return maxDifference;
}
After some attempts, I end up with this:
int iMax = N - 1;
int min = int.MaxValue, max = int.MinValue;
for (int i = 0; i < iMax; i++) {
if (min > A[i]) min = A[i];
if (max < A[N - i - 1]){
iMax = N - i - 1;
max = A[iMax];
}
}
int largestDiff = max - min;
NOTE: I have just tested it with some cases. Please if you find any case in which it doesn't work, let me know in the comment. I'll try to improve it or remove the answer. Thanks!
int FirstIndex = -1;
int SecondIndex = -1;
int diff = 0;
for (int i = A.Length-1; i >=0; i--)
{
int FirstNo = A[i];
int tempDiff = 0;
for (int j = 0; j <i ; j++)
{
int SecondNo = A[j];
tempDiff = FirstNo - SecondNo;
if (tempDiff > diff)
{
diff = tempDiff;
FirstIndex = i;
SecondIndex = j;
}
}
}
MessageBox.Show("Diff: " + diff + " FirstIndex: " + (FirstIndex+1) + " SecondIndex: " + (SecondIndex+1));
PHP Solution
<?php
$a = [0,5,0,5,0];
$max_diff = -1;
$min_value = $a[0];
for($i = 0;$i<count($a)-1;$i++){
if($a[$i+1] > $a[$i]){
$diff = $a[$i+1] - $min_value;
if($diff > $max_diff){
$max_diff = $diff;
}
} else {
$min_value = $a[$i+1];
}
}
echo $max_diff;
?>
We can do it in a much simpler way by calculating biggest and smallest element of the array. I know that you're also looking for time complexity. But for anyone looking to understand and solve this problem in a simple and easy to understand way, then here is my code:
#include<stdio.h>
#define N 6
int main()
{
int num[N], i, big, small, pos = 0;
printf("Enter %d integer numbers\n", N);
for(i = 0; i < N; i++)
scanf("%d", &num[i]);
big = small = num[0];
for(i = 1; i < N; i++)
{
if(num[i] > big)
{
big = num[i];
pos = i;
}
}
for(i = 1; i < pos; i++)
{
if(num[i] < small)
small = num[i];
}
printf("The largest difference is %d, ", (big - small));
printf("and its between %d and %d.\n", big, small);
return 0;
}
Output:
Enter 6 integer numbers
7
9
5
6
13
2
The largest difference is 8, and its between 13 and 5.
Source: C Program To Find Largest Difference Between Two Elements of Array
C++ solution for MaxProfit of codility test task giving 100/100 https://app.codility.com/programmers/lessons/9-maximum_slice_problem/max_profit/
int Max(vector<int> &A)
{
if (A.size() == 1 || A.size() == 0)
return 0;
int min_price = A[0];
int max_val = 0;
for (int i = 1; i < A.size(); i++)
{
max_val = std::max(max_val, A[i] - min_price);
min_price = std::min(min_price, A[i]);
}
return max_val;
}
My 100% JavaScript solution with O(N) time complexity:
function solution(A) {
// each element of array A is an integer within the range [0..200,000]
let min = 200000;
// The function should return 0 if it was impossible to gain any profit.
let maxDiff = 0;
for (const a of A) {
min = Math.min(min, a);
// find the maximum positive difference (profit) between current global minimum and current value of a
maxDiff = Math.max(maxDiff, a - min);
}
return maxDiff;
}
function solution(A) {
var n = A.length;
var min = Infinity, max = -Infinity, maxNet=0;
// find smallest and largest in the array following each other
for(let i = 0; i < n; i++){
if(A[i]<min) { // if you are updating the min you cannot consider the old max
min = A[i];
max = -Infinity;
} else if(A[i]> max){
max = A[i];
}
if(max!=-Infinity && max-min>maxNet) maxNet = max-min;
}
return maxNet;
}
PHP solution for MaxProfit of codility test task giving 100/100 found at http://www.rationalplanet.com/php-related/maxprofit-demo-task-at-codility-com.html
function solution($A) {
$cnt = count($A);
if($cnt == 1 || $cnt == 0){
return 0;
}
$max_so_far = 0;
$max_ending_here = 0;
$min_price = $A[0];
for($i = 1; $i < $cnt; $i++){
$max_ending_here = max(0, $A[$i] - $min_price);
$min_price = min($min_price, $A[$i]);
$max_so_far = max($max_ending_here, $max_so_far);
}
return $max_so_far;
}
100% score JavaScript solution.
function solution(A) {
if (A.length < 2)
return 0;
// Init min price and max profit
var minPrice = A[0];
var maxProfit = 0;
for (var i = 1; i < A.length; i++) {
var profit = A[i] - minPrice;
maxProfit = Math.max(maxProfit, profit);
minPrice = Math.min(minPrice, A[i]);
}
return maxProfit;
}
Python solution
def max_diff_two(arr):
#keep tab of current diff and min value
min_value = arr[0]
#begin with something
maximum = arr[1] - arr[0]
new_min = min_value
for i,value in enumerate(arr):
if i == 0:
continue
if value < min_value and value < new_min:
new_min = value
current_maximum = value - min_value
new_maximum = value - new_min
if new_maximum > current_maximum:
if new_maximum > maximum:
maximum = new_maximum
min = new_min
else:
if current_maximum > maximum:
maximum = current_maximum
return maximum
100% for Javascript solution using a more elegant functional approach.
function solution(A) {
var result = A.reverse().reduce(function (prev, val) {
var max = (val > prev.max) ? val : prev.max
var diff = (max - val > prev.diff) ? max - val : prev.diff
return {max: max, diff: diff}
}, {max: 0, diff: 0})
return result.diff
}

Categories

Resources