Jerry's Blog

Recording what I learned everyday

View on GitHub


7 July 2019

Angular (23) -- Authentication

by Jerry Zhang

LeetCode Day 2: P53. Maximum Subarray

题目

一个整数数组,找到一个连续的subarray,使其得到的sum最大,返回sum

Input: [-2,1,-3,4,-1,2,1,-5,4], Output: 6 Explanation: [4,-1,2,1] has the largest sum = 6.

我的思路:

问题的关键在于数的正负。假如全是正数,那肯定全要,才能使整个数组的和最大。但如果有负的怎么办?比如上面的例子,其实可以从两头切, -2肯定是不要的。1为什么不要了呢?````因为后面还有-3,总和小于零,赔了。如果知道了所有子数组的和,那切掉不切掉就很容易决定了。分析到此, 我们很明显发现这是一个动态规划问题。我们只需要从两侧向中间推进,只要遇到加和小于零的子数组就切掉。最后中间剩下的一定是最大的。 现在问题是推进到什么时候为止呢?从一边推进还是从两侧推进?上面的分析可能是不对的。。。

但我依旧觉得这是一个动态规划问题。因为只要记录下每个小数组的正负,我就能决定大数组到底要还是不要这一段。完全符合最优子结构(optimal substructure)这类问题的性质。

https://blog.csdn.net/u013309870/article/details/75193592

提示中说,首先是O(n)的解法,更好的方法是divide and conquer。

放弃了,看答案:

看了下答案,也是动态规划的解法。每个数都与前面统计过的最大值进行比较,如果加上前面的还不如不要呢,就直接把前面的累计值扔了, 只要当前这个值。

最优代码

public class E_53_Maximum_SubArray {
    public static int maxSubArray(int[] nums) {
        if(nums.length == 1) {
            return nums[0];
        }
        int max = nums[0];
        int curr = nums[0];
        for(int i = 1; i < nums.length; i++) {
            curr = ((curr + nums[i]) > nums[i]) ? (curr + nums[i]) : nums[i];
            max = (max > curr) ? max : curr;
        }
        return max;
    }

    public static void main(String[] args) {
        int[] nums = {-2,1,-3,4,-1,2,1,-5,4};
        int max = maxSubArray(nums);
        System.out.println("max = " + max);
    }
}

时间复杂度:O(n)

Creating & Storing the User Data

Create a User Model

export class User {
  constructor(public email: string,
              public id: string,
              private _token: string,
              private _tokenExpirationDate: Date
  ) {}

  get token() {
    if (!this._tokenExpirationDate || new Date() > this._tokenExpirationDate) {
      return null;
    }
    return this._token;
  }
}

Create a user subject to emit the new user.

user = new Subject<User>();

Use the tap operator to create a new user and emit it.

signup(email: string, password: string) {
    return this.http.post<AuthResponseData>(
      'https://www.googleapis.com/identitytoolkit/v3/relyingparty/signupNewUser?key=AIzaSyCQUonbyGcWNNCk-jS2WWkgpR3U0TtkIdA',
      {
        email: email,
        password: password,
        returnSecureToken: true
      }
    ).pipe(catchError(this.handleError),
      tap(resData => {
      this.handleAuthentication(resData.email, resData.localId, resData.idToken, +resData.expiresIn);
    }));
  }
  
private handleAuthentication(email: string, userId: string, token: string, expiresIn: number) {
    const expirationDate = new Date(new Date().getTime() + expiresIn * 1000);
    const user = new User(email, userId, token, expirationDate);
    this.user.next(user);
  }

Firebase gives us the expiresIn as a string that is the number of seconds in which the ID token expires. Therefore, we need to convert this number to a Date Object.

new Date().getTime() is the current timestamp in milliseconds since 1970.

Adding a plus sign before a string can convert this string to a number.

Auth State in the UI

After subscribing the login and sign up Observable, we can navigate the use to another page.

authObservable.subscribe(resData => {
      console.log(resData);
      this.isLoading = false;
      this.router.navigate(['/recipes']);
    }, errorMessage => {
      console.log(errorMessage);
      this.error = errorMessage;
      this.isLoading = false;
    });

Use a user Subject to emit to all the app any change of the user.

user = new Subject<User>();

Then subscribe this subject in the header component. Change the UI on the header by checking whether the response user is null.

ngOnInit() {
    this.userSub = this.authService.user.subscribe(user => {
      this.isAuthenticated = !!user;
      console.log(!user);
      console.log(!!user);
    });
  }
tags: Angular